Tuesday, March 13, 2018

collision detection - What type of Collider should I add to a LineRenderer?



I am currently building a game where I need to generate some wires (as Bézier curves) using LineRenderer. After changing the width of each line


lineRenderer.SetWidth (0.15f, 0.15f);

I am attaching an EdgeCollider2D to the same game object (specifying the same points used in generating the Bézier curve). This seems to work. However, I would like to be able to know if the Mouse Pointer is at any time over the EdgeCollider2D (something similar to the popular Fruit Ninja game). I'm using Raycast as follows:


void CastRay() {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast (ray.origin, ray.direction, Mathf.Infinity);

if (hit) {
Debug.Log (hit.collider.gameObject.name);

}
}

I'm calling the CastRay method inside the Update method. Because EdgeCollider2D does not have width (as expected), the log message is never produced.


Do I need to use a different type of Collider? Do I need to call CastRay somewhere else?



Answer



Ok. After some experiments I ended up replacing the EdgeCollider2D with a PolygonCollider2D. I generated the collider points (taking the width of the wire into account) by computing the Euclidean distance between two consecutive points on the curve (you need to iterate through all the points) and the perpendicular on the distance vector (using the cross product).


Here's an example:


List edgePoints = new List ();
PolygonCollider2D collider = new PolygonCollider2D ();


for (int j = 0; j < bezierPoints.Count; j++) {
Vector2 distanceBetweenPoints = bezierPoints[j-1] - bezierPoints[j];
Vector3 crossProduct = Vector3.Cross (distanceBetweenPoints, Vector3.forward);

Vector2 up = (wireWidth / 2) * new Vector2(crossProduct.normalized.x, crossProduct.normalized.y) + bezierPoints [j-1];
Vector2 down = -(wireWidth / 2) * new Vector2(crossProduct.normalized.x, crossProduct.normalized.y) + bezierPoints [j-1];

edgePoints.Insert(0, down);
edgePoints.Add(up);


if (j == bezierPoints.Count - 1) {
// Compute the values for the last point on the Bezier curve
up = (wireWidth / 2) * new Vector2(crossProduct.normalized.x, crossProduct.normalized.y) + bezierPoints [j];
down = -(wireWidth / 2) * new Vector2(crossProduct.normalized.x, crossProduct.normalized.y) + bezierPoints [j];

edgePoints.Insert(0, down);
edgePoints.Add(up);
}
}


collider.points = edgePoints.ToArray();

This will generate a Polygon collider that will wrap the entire wire (curve) based on the wireWdth.


PolygonCollider2D on top of Line Renderer


I wanted to post the solution in case someone else is having similar issues.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...