Draw a Line on Canvas With Mouse Position Unity 3D - c#

I followed a tutorial to draw a line using mouse position, the line will be drawn inside the canvas. But when running it, the line didn't drawn! and it gives me this error:
NullReferenceException: Object reference not set to an instance of an object
What's wrong in my code?
Here's the script:
public GameObject Line;
GameObject CurrentLine;
LineRenderer linerenderer;
private List<Vector2> FingerPositions;
public Canvas Can;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
CreateLine();
}
if (Input.GetMouseButton(0))
{
Vector2 tempfingerpos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if (Vector2.Distance(tempfingerpos, FingerPositions[FingerPositions.Count - 1]) > 0.1f)
{
UpdateLine(tempfingerpos);
}
}
}
void CreateLine()
{
CurrentLine = Instantiate(Line, Vector3.zero, Quaternion.identity);
linerenderer = CurrentLine.GetComponent<LineRenderer>();
FingerPositions.Clear();
FingerPositions.Add(Camera.main.ScreenToWorldPoint(Input.mousePosition));
FingerPositions.Add(Camera.main.ScreenToWorldPoint(Input.mousePosition));
linerenderer.SetPosition(0, FingerPositions[0]);
linerenderer.SetPosition(0, FingerPositions[1]);
CurrentLine.transform.SetParent(Can.transform, false);
}
void UpdateLine(Vector2 NewFingerPos)
{
FingerPositions.Add(NewFingerPos);
linerenderer.positionCount ++;
linerenderer.SetPosition(linerenderer.positionCount - 1, NewFingerPos);
}

My suggestion is to try first to draw line renderer with fixed positions(You can add two empty objects and then draw line renderer between those objects).
And if that works, then move to the logic with fingers.
Keep in mind that you can't see line renderer if you are using screen space overlay, so you must use Canvas - World Space to see it over the canvas.

replace this
private List FingerPositions;
with this
private List<Vector2> FingerPositions = new List<Vector2>();

Related

2D line renderer reflection issue - Unity

I make a 2d line renderer reflection on a specific object tag, it's working but only on the left side when on the right side the reflection is not showing, I don't have any idea why because when my script is on 3d it's working fine.
this is a script that I convert from 3D and I change it all to 2D.
public int reflections;
public float maxLength;
private LineRenderer lineRenderer;
public LayerMask layerMask;
private Ray2D ray;
private RaycastHit2D hit;
private void Awake()
{
lineRenderer = GetComponent<LineRenderer>();
}
private void Update()
{
ray = new Ray2D(transform.position, transform.up);
lineRenderer.positionCount = 1;
lineRenderer.SetPosition(0, transform.position);
float remainingLength = maxLength;
for (int i = 0; i < reflections; i++)
{
hit = Physics2D.Raycast(ray.origin, ray.direction, remainingLength, layerMask);
if (hit)
{
lineRenderer.positionCount += 1;
lineRenderer.SetPosition(lineRenderer.positionCount - 1, hit.point);
remainingLength -= Vector2.Distance(ray.origin, hit.point);
ray = new Ray2D(hit.point, Vector2.Reflect(ray.direction, hit.normal));
if (hit.collider.tag != "Reflect")
break;
}
else
{
lineRenderer.positionCount += 1;
lineRenderer.SetPosition(lineRenderer.positionCount - 1, ray.origin + ray.direction * remainingLength);
}
}
}
PREVIEW
When going to the right.
When going to left.
Sometimes it flickers too, I don't have any idea how this happens, I thought it was because order layer I have changed this but nothing happen.
In regard to the flickering, this is occuring due to a clipping issue with the collided object and the line itself.
Inside of the condition:
if (hit)
Adjust the code to be the following:
// Get the reflected vector of the raycast.
Vector2 updatedDirection = Vector2.Reflect(ray.direction, hit.normal);
// Create new Ray object & set origin to be 0.01f away from hitpoint so the line is not colliding with the gameobject collider.
ray = new Ray2D(hit.point + updatedDirection * 0.01f, updatedDirection);
You can find out more from these links:
https://answers.unity.com/questions/1602542/line-renderer-flickering-when-updated-in-runtime.html
https://answers.unity.com/questions/1690411/help-with-reflecting-in-2d.html?childToView=1690554#comment-1690554
As for the reason the line is not reflecting on the right wall, this is more than likely due to the gameObjects tag not being set to "Reflect". You are only creating a new reflected line when colliding with an object with that tag. Double check that the right walls gameObject has the tag "Reflect" set in the inspector.

How do i set the velocity of a sprite to the opposite direction of the mouse pointer at a certain speed?

/*I am making a 2d game in Unity that works similarly to billiards, but with other aspects. When the player holds down button 0, a line drags away from the ball to show the direction and speed the ball will be hit off in. I don't know how to set that velocity or how to add a force like that.
I've tried setting the velocity directly, then adding fake frictions, but that didn't work too well. I also tried adding a force to the ball, and also making an empty game object that follows the pointer with a point effecter to repel the ball. But I cant seem to get anything to work.
--Also I apologize for the messy code, i'm still kinda new to this
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LineDrawer : MonoBehaviour
{
public Transform tr; //this is the transform and rigid body 2d of the
ball
public Rigidbody2D rb;
public LineRenderer line; // the line rendered is on the ball
public float hitForce = 10;
// Start is called before the first frame update
void Start()
{
line = GetComponent<LineRenderer>();
line.SetColors(Color.black, Color.white);
}
// Update is called once per frame
void FixedUpdate()
{
line.SetPosition(0, tr.position - new Vector3(0, 0, 0));
if (Input.GetMouseButton(0)&&PlayerPrefs.GetInt("Moving")==0)
{
line.SetWidth(.25f, .25f);
line.SetPosition(1, Camera.main.ScreenToWorldPoint(Input.mousePosition));
float len = Vector2.Distance(line.GetPosition(0), line.GetPosition(1)); //this is for determining the power of the hit
}
else
{
line.SetWidth(0, 0); //make the line invisible
}
if (Input.GetMouseButtonUp(0) && (PlayerPrefs.GetInt("Moving")==0))
{
Vector2.Distance(Input.mousePosition, tr.position)*100;
Debug.Log("Up");
rb.velocity = //this is what i cant work out
PlayerPrefs.SetInt("Moving", 1);
}
}
}
//5 lines from the bottom is where i'm setting the velocity.
Just rewrite your script to the following:
using UnityEngine;
public class Ball : MonoBehaviour
{
private LineRenderer line;
private Rigidbody2D rb;
void Start()
{
line = GetComponent<LineRenderer>();
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
line.SetPosition(0, transform.position);
if (Input.GetMouseButton(0))
{
line.startWidth = .05f;
line.endWidth = .05f;
line.SetPosition(1, Camera.main.ScreenToWorldPoint(Input.mousePosition));
}
else
{
line.startWidth = 0;
line.endWidth = 0;
}
if (Input.GetMouseButtonUp(0))
{
Vector2 direction = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
direction.Normalize();
rb.AddForce(direction * 3f, ForceMode2D.Impulse);
}
}
}

Camera Lock-On behind player while targeting enemy

Something similar to either Rocket League or Kingdom Hearts, where the camera locks onto the target but it still keeps the player in the center of the screen. I've placed the camera as a child of the player, but after trying out various solutions from others I'm still unable to position the camera correctly.
public List<Transform> targets;
private void EnemyCam()
{
Vector3 centerPoint = GetCenterPoint();
transform.LookAt(centerPoint);
Vector3 newPos = centerPoint;
transform.position = Vector3.SmoothDamp(transform.position, newPos, ref
velocity, smoothTime);
}
private Vector3 GetCenterPoint()
{
if (targets.Count == 1)
return targets[0].position;
var bounds = new Bounds(targets[0].position, Vector3.zero);
for (int i = 0; i < targets.Count; ++i)
bounds.Encapsulate(targets[i].position);
return bounds.center;
}
If you are moving you camera by script, it shouldn't be child of the moving player at the same time. You are setting up some position from script, but at the same time, this position is modified also by parent object so final result is unpredictable.

Debug.DrawLine not showing in the GameView

I'm working on a 2D Unity app and I'm encountering some weird behavior.
This code works just fine.
Debug.DrawLine(button1.transform.position, button2.transform.position, Color.green);
When I run the app, I see a green line in the Scene view.
But nothing appears in the Game view when I have the following line.
Physics2D.Linecast(button1.transform.position, button2.transform.position);
I'm confused as to how Unity is able to draw a line between these two buttons, but for some reason, it's just not doing it in the Game view.
Any idea how I'd troubleshoot this?
Just line Serlite said, Physics2D.Linecast is not used to draw a line but to detect if there is an object in the middle of two objects with raycast. It has nothing to do with drawing lines.
As you already know, Debug.DrawLine will only work in the Scene view unless Gizmos is enabled. You can just LineRenderer or the GL functions to draw lines which will work without enabling Gizmos and will also work in a build.
Here is a helper class for drawing line in the Game and Scene view.
public struct LineDrawer
{
private LineRenderer lineRenderer;
private float lineSize;
public LineDrawer(float lineSize = 0.2f)
{
GameObject lineObj = new GameObject("LineObj");
lineRenderer = lineObj.AddComponent<LineRenderer>();
//Particles/Additive
lineRenderer.material = new Material(Shader.Find("Hidden/Internal-Colored"));
this.lineSize = lineSize;
}
private void init(float lineSize = 0.2f)
{
if (lineRenderer == null)
{
GameObject lineObj = new GameObject("LineObj");
lineRenderer = lineObj.AddComponent<LineRenderer>();
//Particles/Additive
lineRenderer.material = new Material(Shader.Find("Hidden/Internal-Colored"));
this.lineSize = lineSize;
}
}
//Draws lines through the provided vertices
public void DrawLineInGameView(Vector3 start, Vector3 end, Color color)
{
if (lineRenderer == null)
{
init(0.2f);
}
//Set color
lineRenderer.startColor = color;
lineRenderer.endColor = color;
//Set width
lineRenderer.startWidth = lineSize;
lineRenderer.endWidth = lineSize;
//Set line count which is 2
lineRenderer.positionCount = 2;
//Set the postion of both two lines
lineRenderer.SetPosition(0, start);
lineRenderer.SetPosition(1, end);
}
public void Destroy()
{
if (lineRenderer != null)
{
UnityEngine.Object.Destroy(lineRenderer.gameObject);
}
}
}
Usage:
LineDrawer lineDrawer;
void Start()
{
lineDrawer = new LineDrawer();
}
void Update()
{
lineDrawer.DrawLineInGameView(Vector3.zero, new Vector3(0, 40, 0f), Color.blue);
}
When done, you can call lineDrawer.Destroy();.
Debug.DrawLine renders a line gizmo into the Scene View.
If you want a line rendered into the Game View, use a Line Renderer Component.
Line Renderer Docs

Lock camera position in VR

I'm playing around with VR a bit, so far I can move a character around and such. However the position of the camera is changing. I want my camera to be in a fixed position and only be able to change up/down position and the normal rotation with the HMD.
void Start ()
{
startPos = transform.localPosition;
parentObj = transform.root;
}
void Update()
{
ResetVR();
}
void ResetVR()
{
if (parentObj != null)
{
startPos -= InputTracking.GetLocalPosition(VRNode.CenterEye);
transform.localRotation = Quaternion.Inverse(parentObj.localRotation);
}
}
With this my character rotates normally but the camera won't stay in a fixed position.
For example, if I rotate 90 degrees, the camera ends up left of the character. I want the camera stay in a fixed position.
You only want to up/down. This is the-same as rotating around x-axis only. Get the original position. Convert the Quaternion to angle then rotate with transform.localEulerAngles instead of transform.localRotation.Overwrite the other two axis(y,z) with originalPos variables before rotating. You may need to modify this to get it working properly.
Transform parentObj;
Vector3 startPos;
Vector3 originalPos;
void Start()
{
startPos = transform.localPosition;
originalPos = transform.localPosition;
parentObj = transform.root;
}
void Update()
{
ResetVR();
}
void ResetVR()
{
if (parentObj != null)
{
startPos -= InputTracking.GetLocalPosition(VRNode.CenterEye);
Quaternion tempRot = Quaternion.Inverse(parentObj.localRotation);
Vector3 newAngle = tempRot.eulerAngles;
transform.localEulerAngles = new Vector3(newAngle.x, originalPos.y, originalPos.z);
}
}
You might want to have a look at this rule.
See Unity's documentation about this.

Categories