How to destroy a line when line renderer is used in Unity? - c#

So I only want one line on screen at a time. I would like to destroy the current line when a ball collides or another line is drawn. Here is my code so far. It creates a line renderer with two points, adds a Box collider. I've tried making a loop and setting the vector points back to zero.
Every time I add a OnCollisonEnter2D I cannot get the Line to register that it hit a ball. In the Ball script I can get the Log to print Hit when the Ball hits the collider.
using System.Runtime.CompilerServices;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.UI;
public class Player1 : MonoBehaviour
{
private LineRenderer line; // Reference to LineRenderer
private Vector3 mousePos;
public Vector3 startPos; // Start position of line
public Vector3 endPos; // End position of line
void Update()
{
GetLine(); // On mouse down new line will be created
}
private void GetLine()
{
if (Input.GetMouseButtonDown(0))
{
if (line == null)
CreateLine();
SetFirstPos();
}
else if (Input.GetMouseButtonUp(0))
{
if (line)
{
SetSecondPos();
AddColliderToLine();
line = null;
}
}
else if (Input.GetMouseButton(0))
{
if (line)
{
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 0;
line.SetPosition(1, mousePos);
}
}
}
// Following method creates line runtime using Line Renderer component
private void CreateLine()
{
line = new GameObject("Line").AddComponent<LineRenderer>();
line.positionCount = 2;
line.numCapVertices = 2;
line.startWidth = .25f;
line.endWidth = .25f;
line.startColor = Color.black;
line.endColor = Color.black;
line.useWorldSpace = true;
}
// Following method adds collider to created line
private void AddColliderToLine()
{
BoxCollider2D col = new GameObject("Collider").AddComponent<BoxCollider2D>();
col.transform.parent = line.transform; // Collider is added as child object of line
float lineLength = Vector3.Distance(startPos, endPos);// length of line
lineLength.ToString();
col.size = new Vector3(lineLength, 0.25f, 1f); // size of collider is set where X is length of
line, Y is width of line, Z will be set as per requirement
Vector3 midPoint = (startPos + endPos) / 2;
col.transform.position = midPoint; // setting position of collider object
// Following lines calculate the angle between startPos and endPos
float angle = (Mathf.Abs(startPos.y - endPos.y) / Mathf.Abs(startPos.x - endPos.x));
if ((startPos.y < endPos.y && startPos.x > endPos.x) || (endPos.y < startPos.y && endPos.x >
startPos.x))
{
angle *= -1;
}
angle = Mathf.Rad2Deg * Mathf.Atan(angle);
col.transform.Rotate(0, 0, angle);
}
//Sets the first position
private void SetFirstPos()
{
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 0;
line.SetPosition(0, mousePos);
startPos = mousePos;
Debug.Log("Line");
}
//Sets the second position
private void SetSecondPos()
{
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 0;
line.SetPosition(1, mousePos);
endPos = mousePos;
}
//Cannot get it to Log Hit. Line show up in the Hierarchy.
private void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameobject.name =="Line")
{
Debug.Log("Hit!");
}
}
}

If your OnCollisionEnter2D gets called why don't you use just use it?
private void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.name =="Line")
{
Debug.Log("Hit!");
// destroy the hit line
GameObject.Destroy(collision.gameObject);
}
}
If you want the line to be destroyed once a new one gets created you have to store it and destroy it manually:
public class Player1 : MonoBehaviour
{
private GameObject lastLine;
[...]
private void GetLine()
{
if (Input.GetMouseButtonDown(0))
{
if(lastLine != null)
{
GameObject.Destroy(lastLine);
}
if (line == null)
CreateLine();
SetFirstPos();
}
else if (Input.GetMouseButtonUp(0))
{
if (line)
{
SetSecondPos();
AddColliderToLine();
lastLine = line.gameObject;
line = null;
}
}
[...]
}

Related

Infinite Runner Unity2d

So, when I start the game, my character can jump on the first platform (because that is the manually placed platform), but I cannot jump on the spawned floors. BTW I am able to run on the floors and I know my jump works correctly.
I have tried so many ways of collider detection I am going crazy and I know its a simple fix that I just can't figure out.
I expected my character to be able to jump on the duplicated platforms but the character just doesn't do anything at all.
If anyone is willing to take a look that would be very helpful. - Nick
P.S I know my code is messy.
CODE:
#Code that is on my player script#
using System;
using System.Diagnostics;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using TouchControlsKit;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Text;
using System.IO;
public class Attack : MonoBehaviour
{
const float k_GroundedRadius = .2f; // Radius of the overlap circle to determine if grounded
[SerializeField] private LayerMask m_WhatIsGround;
[SerializeField] private Transform m_GroundCheck;
private bool m_Grounded;
public Collider2D objectCollider;
public Collider2D anotherCollider;
[Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f;
private Timer t;
private Timer a;
private float timeStamp;
private float die = 0;
public GameObject bullet;
private bool m_FacingRight = true;
public float move;
private Vector3 velocity = Vector3.zero;
public GameObject idle_0;
public playscript play;
public Transform player;
private Rigidbody2D m_Rigidbody2D;
[SerializeField] private float m_JumpForce = 200f;
bool swing = false;
bool isgrounded = false;
public bool canJump = false;
bool slide = false;
public Transform groundLayer; // Insert the layer here.
public Vector2 jumpHeight;
private Vector2 touchOrigin = -Vector2.one;
public Vector2 moveSpeed;
public bool run;
Collider2D m_Collider;
// variable to hold a reference to our SpriteRenderer component
private SpriteRenderer mySpriteRenderer;
// This function is called just one time by Unity the moment the component loads
private void Awake()
{
// get a reference to the SpriteRenderer component on this gameObject
mySpriteRenderer = GetComponent<SpriteRenderer>();
animator.SetBool("death", false);
}
public Animator animator;
Animator anim;
int swingHash = Animator.StringToHash("swing");
// Use this for initialization
void Start()
{
timeStamp = Time.time + 5;
m_Collider = GetComponent<Collider2D>();
run = false;
m_Rigidbody2D = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
animator.SetBool("isgrounded", false);
isgrounded = false;
canJump = false;
animator.SetBool("swing", false);
}
private void FixedUpdate()
{
m_Grounded = false;
// The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
// This can be done using layers instead but Sample Assets will not overwrite your project settings.
Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i].gameObject != gameObject)
animator.SetBool("isgrounded", true);
m_Grounded = true;
}
}
// Update is called once per frame
void Update()
{
anotherCollider = GameObject.FindGameObjectWithTag("Ground").GetComponent<BoxCollider2D>();
objectCollider = GameObject.FindGameObjectWithTag("Player").GetComponent<CapsuleCollider2D>();
Vector3 targetVelocity = new Vector2(move * 2f, m_Rigidbody2D.velocity.y);
m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref velocity, m_MovementSmoothing);
animator.SetBool("run", true);
if (move > 0 && !m_FacingRight)
{
// ... flip the player.
Flip();
}
// Otherwise if the input is moving the player left and the player is facing right...
else if (move < 0 && m_FacingRight)
{
// ... flip the player.
Flip();
}
int horizontal = 0; //Used to store the horizontal move direction.
int vertical = 0; //Used to store the vertical move direction.
#if UNITY_STANDALONE || UNITY_WEBPLAYER
//Check if we are running on iOS, Android, Windows Phone 8 or Unity iPhone
#elif UNITY_IOS || UNITY_ANDROID || UNITY_WP8 || UNITY_IPHONE
//Check if Input has registered more than zero touches
if (Input.touchCount > 0)
{
//Store the first touch detected.
Touch myTouch = Input.touches[0];
//Check if the phase of that touch equals Began
if (myTouch.phase == TouchPhase.Began)
{
//If so, set touchOrigin to the position of that touch
touchOrigin = myTouch.position;
}
//If the touch phase is not Began, and instead is equal to Ended and the x of touchOrigin is greater or equal to zero:
else if (myTouch.phase == TouchPhase.Ended && touchOrigin.x >= 0)
{
//Set touchEnd to equal the position of this touch
Vector2 touchEnd = myTouch.position;
//Calculate the difference between the beginning and end of the touch on the x axis.
float x = touchEnd.x - touchOrigin.x;
//Calculate the difference between the beginning and end of the touch on the y axis.
float y = touchEnd.y - touchOrigin.y;
//Set touchOrigin.x to -1 so that our else if statement will evaluate false and not repeat immediately.
touchOrigin.x = -1;
//Check if the difference along the x axis is greater than the difference along the y axis.
if (Mathf.Abs(x) > Mathf.Abs(y))
//If x is greater than zero, set horizontal to 1, otherwise set it to -1
horizontal = x > 0 ? 1 : -1;
else
//If y is greater than zero, set horizontal to 1, otherwise set it to -1
vertical = y > 0 ? 1 : -1;
}
}
#endif
if (TCKInput.GetAction("jumpBtn", EActionEvent.Up))
{
animator.SetBool("jump", false);
}
if (TCKInput.GetAction("jumpBtn", EActionEvent.Down) && m_Grounded == true)
{
animator.SetBool("jump", true);
m_Grounded = false;
m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
}
if (TCKInput.GetAction("fireBtn", EActionEvent.Down))
{
animator.SetBool("swing", true);
m_Collider.enabled = !m_Collider.enabled;
}
if (TCKInput.GetAction("fireBtn", EActionEvent.Up))
{
animator.SetBool("swing", false);
m_Collider.enabled = !m_Collider.enabled;
}
if (TCKInput.GetAction("slideBtn", EActionEvent.Down))
{
if (timeStamp <= Time.time)
{
animator.SetBool("slide", true);
GameObject b = (GameObject)(Instantiate(bullet, transform.position + transform.right * 1.5f, Quaternion.identity));
b.GetComponent<Rigidbody2D>().AddForce(transform.right * 1000);
timeStamp = Time.time + 5;
}
}
if (TCKInput.GetAction("slideBtn", EActionEvent.Up))
{
animator.SetBool("slide", false);
}
if (TCKInput.GetAction("right", EActionEvent.Press))
{
move = -1;
}
if (TCKInput.GetAction("right", EActionEvent.Up))
{
animator.SetBool("run", false);
}
if (TCKInput.GetAction("left", EActionEvent.Press))
{
move = 1;
}
if (TCKInput.GetAction("left", EActionEvent.Up))
{
animator.SetBool("run", false);
}
if (objectCollider.IsTouching(anotherCollider))
{
canJump = true;
}
else
{
canJump = false;
}
}
private void Flip()
{
// Switch the way the player is labelled as facing.
m_FacingRight = !m_FacingRight;
// Multiply the player's x local scale by -1.
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
void Hurt()
{
move = 4;
SceneManager.LoadScene(0);
}
protected void OnCollisionEnter2D(Collision2D collision)
{
EnemyHealth3 enemy = collision.collider.GetComponent<EnemyHealth3>();
if (enemy != null)
{
move = 0;
animator.SetBool("death", true);
m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
StartCoroutine(ExecuteAfterTime(.1));
}
}
IEnumerator ExecuteAfterTime(double time)
{
yield return new WaitForSeconds((float)time);
Hurt();
}
}
#Code that is on the floor spawner script#
using UnityEngine;
using System.Collections;
public class Floor_Spawn_Script : MonoBehaviour
{
public GameObject[] obj;
private float oldPosition;
private float currentPosition;
private float ctr = 0;
private float inte = 10.19f;
// Use this for initialization
private void Start()
{
oldPosition = transform.position.x;
AddRoom(ctr * inte);
ctr += 1;
AddRoom(ctr * inte);
ctr += 1;
AddRoom(ctr * inte);
}
// Update is called once per frame
void Update()
{
currentPosition = transform.position.x;
if ((currentPosition - oldPosition) <= 9.595f)
{
AddRoom(ctr * inte);
oldPosition = transform.position.x;
ctr += 1;
}
}
void AddRoom(float roomCenter)
{
GameObject room = (GameObject)Instantiate(obj[Random.Range(0, obj.Length)]);
room.transform.position = new Vector3(roomCenter, 0f, 10f);
}
}```

Draw a line with Edge collider 2D using LineRenderer programmatically, but the collider is in wrong place in Unity

I want the player to draw a line through the mouse, and this line has a collider, but this collider appears in the wrong place.
I have tried these methods with ScreenToWorldPoint, ScreenToViewportPoint and ScreenPointToRay, but these results are not what I want.
public class DrawLine : MonoBehaviour
{
public GameObject linePrefab;
public GameObject currentLine;
public LineRenderer lineRenderer;
public EdgeCollider2D edgeCollider;
public List<Vector2> fingerPositions;
public List<Vector2> fingerWorldPositions;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
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]) > .1f)
{
UpdateLine(tempFingerPos);
}
}
}
void CreateLine()
{
currentLine = Instantiate(linePrefab, Vector2.zero, Quaternion.identity);
lineRenderer = currentLine.GetComponent<LineRenderer>();
edgeCollider = currentLine.GetComponent<EdgeCollider2D>();
fingerPositions.Clear();
Vector3 tempMousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
fingerPositions.Add(tempMousePosition);
fingerPositions.Add(tempMousePosition);
lineRenderer.SetPosition(0, fingerPositions[0]);
lineRenderer.SetPosition(1, fingerPositions[1]);
edgeCollider.points = fingerPositions.ToArray();
}
void UpdateLine(Vector2 newFingerPos)
{
fingerPositions.Add(newFingerPos);
lineRenderer.positionCount++;
lineRenderer.SetPosition(lineRenderer.positionCount - 1, newFingerPos);
edgeCollider.points = fingerPositions.ToArray();
}
}
The black line is drawn with a mouse and the green line is Edge collider 2D.
I had your exact same problem some time ago in a project of mine. I fixed it by adjusting the transform.position of the linerenderer object to the location of the next point. And after setting the points, i would reset the position of the gameobject to zero (last line of code). This worked for me, because my gameobject should always be at absolute zero. But if yours doesn't, then just change it to use relative position and child it to an gameobject if it isnt already.
Here is my code, I hope it helps you.
public GameObject LineDrawPrefab;
private LineRenderer lineRenderer;
private EdgeCollider2D edgeCollider;
private List<Vector2> edgePoints;
private GameObject activeLineGameObject;
private List<GameObject> lineGameObjects;
private void StartLine(Vector3 start, Color color)
{
var targetPos = new Vector3 { x = start.x, y = start.y, z = 0.1f };
drawing = true;
activeLineGameObject = Instantiate(LineDrawPrefab, Vector3.zero, Quaternion.identity);
lineGameObjects.Add(activeLineGameObject);
lineRenderer = activeLineGameObject.GetComponent<LineRenderer>();
edgeCollider = activeLineGameObject.GetComponent<EdgeCollider2D>();
lineRenderer.sortingOrder = 1;
lineRenderer.material = LineRendererMaterial;
lineRenderer.startColor = color;
lineRenderer.endColor = color;
lineRenderer.startWidth = 0.3f;
lineRenderer.endWidth = 0.3f;
lineRenderer.SetPosition(0, targetPos);
lineRenderer.SetPosition(1, targetPos);
edgePoints.Clear();
edgePoints.Add(targetPos);
edgeCollider.points = edgePoints.ToArray();
}
private void ExtendLine(Vector3 nextpoint)
{
if (lineRenderer == null))
{
StartLine(Camera.main.ScreenToWorldPoint(Input.mousePosition), color);
return;
}
var targetPos = new Vector3 { x = nextpoint.x, y = nextpoint.y, z = 0.1f };
lineRenderer.positionCount += 1;
lineRenderer.SetPosition(lineRenderer.positionCount - 1, lineRenderer.transform.position = targetPos); // manipulate position to avoid the collider from spawning out of the object.
edgePoints.Add(nextpoint);
edgeCollider.points = edgePoints.ToArray();
activeLineGameObject.transform.position = Vector3.zero; // reset position
}
Edit: An additional tip. I (and you) used Camera.main here. This is not performant because it does an expensive lookup every time it is called.
(GameObject.FindGameObjectWithTag("MainCamera").GetComponent<Camera>())
I suggest to cache it in start or awake and then reuse that variable. This can potentially be a huge performance gain.
private Camera mainCamera;
private void Start()
{
mainCamera = Camera.main;
}

Unity3d drawing with whitespaces

I drew lines using LineRenderer. Game is 2d. What I want now is to create whitespace in line with the line on the gameobject with collider.
Here is the code I use for drawing and adding collider to line. What I want is not to draw a line on gameobjects, like circles(with CircleCollider2D) or squares(with BoxCollider2D). I want to have two different LineRenderers: one is finishing on collider, second is starting on it. What I'm trying to achieve That square does not hide the line. There is not a line where the square is.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class DrawLine : MonoBehaviour
{
private LineRenderer line;
private bool isMousePressed;
public bool isLeftMousePressed = false;
public List<Vector3> pointsList;
private Vector3 mousePos;
public float width = 0.05f;
// Structure for line points
struct myLine
{
public Vector3 StartPoint;
public Vector3 EndPoint;
};
// -----------------------------------
void Awake()
{
// Create line renderer component and set its property
line = gameObject.AddComponent<LineRenderer>();
line.material = (Material)Resources.Load("Materials/LineMat");
line.startWidth = width;
line.endWidth = width;
line.useWorldSpace = true;
isMousePressed = false;
pointsList = new List<Vector3>();
}
// -----------------------------------
void Update()
{
if (Input.GetMouseButtonDown(1))
{
isLeftMousePressed = true;
}
if (isLeftMousePressed||Game.currentLevel == 0) return;
if (Input.GetMouseButton(0))
{
isMousePressed = true;
}
// Drawing line when mouse is moving(pressed)
if (isMousePressed)
{
if (Input.GetMouseButtonUp(0))
{
isMousePressed = false;
GameObject curve = (GameObject)Instantiate(Resources.Load("Curve"), transform.parent);
curve.GetComponent<DrawLine>().width = width;
if (line.GetPosition(line.positionCount - 1).z == 1) Destroy(gameObject);
else enabled = false;
}
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 0;
if (!pointsList.Contains(mousePos))
{
pointsList.Add(mousePos);
line.positionCount = pointsList.Count;
line.SetPosition(pointsList.Count - 1, (Vector3)pointsList[pointsList.Count - 1]);
try
{
AddColliderToLine(line, (Vector3)pointsList[pointsList.Count - 2], (Vector3)pointsList[pointsList.Count - 1]);
}
catch(Exception e)
{
}
}
}
}
// -----------------------------------
// Following method checks whether given two points are same or not
// -----------------------------------
private bool checkPoints(Vector3 pointA, Vector3 pointB)
{
return (pointA.x == pointB.x && pointA.y == pointB.y);
}
private void AddColliderToLine(LineRenderer line, Vector3 startPoint, Vector3 endPoint)
{
//create the collider for the line
GameObject lcObject = new GameObject("LineCollider");
BoxCollider2D lineCollider = lcObject.AddComponent<BoxCollider2D>();
lcObject.layer = 2; // ignore raycast
//set the collider as a child of your line
lineCollider.transform.parent = line.transform;
// get width of collider from line
float lineWidth = line.endWidth;
// get the length of the line using the Distance method
float lineLength = Vector3.Distance(startPoint, endPoint);
// size of collider is set where X is length of line, Y is width of line
//z will be how far the collider reaches to the sky
lineCollider.size = new Vector3(lineLength, lineWidth);
// get the midPoint
Vector3 midPoint = (startPoint + endPoint) / 2;
// move the created collider to the midPoint
lineCollider.transform.position = midPoint;
//heres the beef of the function, Mathf.Atan2 wants the slope, be careful however because it wants it in a weird form
//it will divide for you so just plug in your (y2-y1),(x2,x1)
float angle = Mathf.Atan2((endPoint.y - startPoint.y), (endPoint.x - startPoint.x));
// angle now holds our answer but it's in radians, we want degrees
// Mathf.Rad2Deg is just a constant equal to 57.2958 that we multiply by to change radians to degrees
angle *= Mathf.Rad2Deg;
//were interested in the inverse so multiply by -1
//angle *= -1;
// now apply the rotation to the collider's transform, carful where you put the angle variable
// in 3d space you don't wan't to rotate on your y axis
lineCollider.transform.Rotate(0, 0, angle);
}
}
If you want to make dotted line, you can see 2D Dotted LineRenderer
And add the collider on the part you want
gameObject.AddComponent<PolygonCollider2D>();
Edit:
Check if mouse is inside the square by raycast
if (isMousePressed)
{
var stopDrawing = false;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
if(hit.transform.tag == "square" || hit.transform.tag == "circle") {
stopDrawing = true;
}
}
if(stopDrawing)
{
// Stop current line, prepare a new List<Vector3> for next line
}
else{
// Continue draw current line
}
}

How to make lines to be more guided in unity

Does anyone how to make lines to be more guided in unity? Guided as in how you use a real life ruler where the drawn lines is not suppose to be straight and the direction of the line or the end point of the line is affected by how you place the ruler. Currently my code, im able to draw lines and collide with the ruler but the lines are more of a freehand drawing. So how do i make it like what i say earlier on.
Heres my code for the line properties script.
void Update()
{
this.GetComponent<Rigidbody> ().useGravity = false;
this.gameObject.GetComponent<Rigidbody> ().constraints =
RigidbodyConstraints.FreezeRotationX |
RigidbodyConstraints.FreezeRotationZ |
RigidbodyConstraints.FreezePositionY |
RigidbodyConstraints.FreezePositionZ;
}
public void OnCollisionStay(Collision col)
{
if (col.gameObject.tag == "Ruler")
{
if (LockPosX == false && LockPosY == false)
{
Debug.Log ("Collision with Ruler");
//line.SetPosition(1 , newPosititon);
//newPosititon.y = col.transform.position.y;
//newPosititon.z = 0;
LockPosY = true;
}
}
}
Heres my code for spawning the line/drawing the line:
void Update ()
{
if(Input.GetMouseButtonDown(0))
{
if (line == null)
{
createLine ();
mousePos = Camera.main.ScreenToWorldPoint (Input.mousePosition);
mousePos.z = 0;
line.SetPosition (0, mousePos);
startPos = mousePos;
}
}
else if(Input.GetMouseButtonUp(0) && line)
{
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 0;
line.SetPosition(1,mousePos);
endPos = mousePos;
addColliderToLine ();
line = null;
currLines++;
}
else if(Input.GetMouseButton(0) && line)
{
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 0;
line.SetPosition(1, mousePos);
}
}
public void createLine()
{
line = new GameObject("Line"+currLines).AddComponent<LineRenderer>();
line.material = material;
line.tag = "DrawnLines";
line.SetVertexCount(2);
line.SetWidth(0.15f,0.15f);
line.useWorldSpace = true;
}
private void addColliderToLine()
{
BoxCollider col = new GameObject("Collider").AddComponent<BoxCollider> ();
col.transform.parent = line.transform;
float lineLength = Vector3.Distance (startPos, endPos);
col.size = new Vector3 (lineLength, 1.0f, 5f);
Vector3 midPoint = (startPos + endPos)/2;
col.transform.position = midPoint;
float angle = (Mathf.Abs (startPos.y - endPos.y) / Mathf.Abs (startPos.x - endPos.x));
if((startPos.y<endPos.y && startPos.x>endPos.x) || (endPos.y<startPos.y && endPos.x>startPos.x))
{
angle*=-1;
}
angle = Mathf.Rad2Deg * Mathf.Atan (angle);
col.transform.Rotate (0, 0, angle);
col.gameObject.AddComponent<LineProperties> ();
col.gameObject.AddComponent<Rigidbody> ();
}
It sounds like what you want to do is snap the position of the user's mouse input to the line created by ruler. If this is the case, you could simply use a simple function to accomplish this before setting the line's position.
//This function returns a point which is a projection from a point to a line.
//The line is regarded infinite. If the line is finite, use ProjectPointOnLineSegment() instead.
public static Vector3 ProjectPointOnLine(Vector3 linePoint, Vector3 lineVec, Vector3 point)
{
//get vector from point on line to point in space
Vector3 linePointToPoint = point - linePoint;
float t = Vector3.Dot(linePointToPoint, lineVec);
return linePoint + lineVec * t;
}
For the first argument - linePoint - you would pass in some point along the ruler's edge. If the ruler gameObject's pivot is along this edge, you can just use the ruler's position. The second argument - lineVec - is the direction vector created by the ruler. Depending on how the ruler's gameObject is oriented, this could be as simple as ruler.transform.forward. Finally, for the third argument, you would pass in Input.mousePosition. If you do not want their input to be snapped to the ruler, but where they started, you would then pass in your Input.mousePosition to the first parameter as well. This will snap it to a line following the same direction as the ruler, but the line will start where their input started.
So your void Update() method becomes:
void Update ()
{
if(Input.GetMouseButtonDown(0))
{
if (line == null)
{
createLine ();
mousePos = Camera.main.ScreenToWorldPoint (ProjectPointOnLine(Input.mousePosition, ruler.transform.forward, Input.mousePosition));
mousePos.z = 0;
line.SetPosition (0, mousePos);
startPos = mousePos;
}
}
else if(Input.GetMouseButtonUp(0) && line)
{
mousePos = Camera.main.ScreenToWorldPoint(ProjectPointOnLine(Input.mousePosition, ruler.transform.forward, Input.mousePosition));
mousePos.z = 0;
line.SetPosition(1,mousePos);
endPos = mousePos;
addColliderToLine ();
line = null;
currLines++;
}
else if(Input.GetMouseButton(0) && line)
{
mousePos = Camera.main.ScreenToWorldPoint(ProjectPointOnLine(Input.mousePosition, ruler.transform.forward, Input.mousePosition));
mousePos.z = 0;
line.SetPosition(1, mousePos);
}
}
Edit
If you need a method to retrieve all of the lines with a specific tag - such as DrawnLines which you use in the createLines() method, you can do something like the following
private void UpdateLines()
{
GameObject[] drawnLineGameObjects = GameObject.FindGameObjectsWithTag("DrawnLines");
foreach (var lineObject in drawnLineGameObjects)
{
LineRenderer drawnLine = lineObject.GetComponent<LineRenderer>();
if (drawnLine != null)
{
// Do stuff to your Line Renderer Here
}
}
}

How to Detect Collision when a gameobject collide with a lineRender?

I want to draw some lines by dragging the mouse. I did that using this script .
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class DrawLine : MonoBehaviour
{
private LineRenderer line;
private bool isMousePressed;
private List<Vector3> pointsList;
private Vector3 mousePos;
// Structure for line points
struct myLine
{
public Vector3 StartPoint;
public Vector3 EndPoint;
};
// -----------------------------------
void Awake()
{
// Create line renderer component and set its property
line = gameObject.AddComponent<LineRenderer>();
line.material = new Material(Shader.Find("Particles/Additive"));
line.SetVertexCount(0);
line.SetWidth(0.1f,0.1f);
line.SetColors(Color.green, Color.green);
line.useWorldSpace = true;
isMousePressed = false;
pointsList = new List<Vector3>();
// renderer.material.SetTextureOffset(
}
// -----------------------------------
void Update ()
{
// If mouse button down, remove old line and set its color to green
if(Input.GetMouseButtonDown(0))
{
isMousePressed = true;
line.SetVertexCount(0);
//pointsList.RemoveRange(0,pointsList.Count);
line.SetColors(Color.green, Color.green);
}
else if(Input.GetMouseButtonUp(0))
{
isMousePressed = false;
}
// Drawing line when mouse is moving(presses)
if(isMousePressed)
{
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z=0;
if (!pointsList.Contains (mousePos))
{
pointsList.Add (mousePos);
line.SetVertexCount (pointsList.Count);
line.SetPosition (pointsList.Count - 1, (Vector3)pointsList [pointsList.Count - 1]);
if(isLineCollide())
{
isMousePressed = false;
line.SetColors(Color.red, Color.red);
}
}
}
}
// -----------------------------------
// Following method checks is currentLine(line drawn by last two points) collided with line
// -----------------------------------
private bool isLineCollide()
{
// if (gameObject.tag == "default") {
if (pointsList.Count < 2)
return false;
int TotalLines = pointsList.Count - 1;
myLine[] lines = new myLine[TotalLines];
if (TotalLines > 1) {
for (int i = 0; i < TotalLines; i++) {
lines [i].StartPoint = (Vector3)pointsList [i];
lines [i].EndPoint = (Vector3)pointsList [i + 1];
}
}
for (int i = 0; i < TotalLines - 1; i++) {
myLine currentLine;
currentLine.StartPoint = (Vector3)pointsList [pointsList.Count - 2];
currentLine.EndPoint = (Vector3)pointsList [pointsList.Count - 1];
if (isLinesIntersect (lines [i], currentLine))
return true;
}
// }
return false;
}
// -----------------------------------
// Following method checks whether given two points are same or not
// -----------------------------------
private bool checkPoints (Vector3 pointA, Vector3 pointB)
{
return (pointA.x == pointB.x && pointA.y == pointB.y);
}
// -----------------------------------
// Following method checks whether given two line intersect or not
// -----------------------------------
private bool isLinesIntersect (myLine L1, myLine L2)
{
if (checkPoints (L1.StartPoint, L2.StartPoint) ||
checkPoints (L1.StartPoint, L2.EndPoint) ||
checkPoints (L1.EndPoint, L2.StartPoint) ||
checkPoints (L1.EndPoint, L2.EndPoint))
return false;
return((Mathf.Max (L1.StartPoint.x, L1.EndPoint.x) >= Mathf.Min (L2.StartPoint.x, L2.EndPoint.x)) &&
(Mathf.Max (L2.StartPoint.x, L2.EndPoint.x) >= Mathf.Min (L1.StartPoint.x, L1.EndPoint.x)) &&
(Mathf.Max (L1.StartPoint.y, L1.EndPoint.y) >= Mathf.Min (L2.StartPoint.y, L2.EndPoint.y)) &&
(Mathf.Max (L2.StartPoint.y, L2.EndPoint.y) >= Mathf.Min (L1.StartPoint.y, L1.EndPoint.y))
);
}
}
enter image description here
Now How to print something when my line collide with some gameobjects in the scene???
It means that when the line collide with my gameobject i want to say go to another scene.
You may use Raycast from LastPosition to CurrentPosition in Update method.
https://docs.unity3d.com/ScriptReference/Physics.Raycast.html
Example:
http://xenforo.unity3d.com/threads/general-purpose-method-for-better-collision-solving.64781/

Categories

Resources