Reputation: 613
I am working on a game where a 2D projectile can ricochet off of walls. I currently have the object itself ricocheting just fine, however I would like an Angry Birds Style HUD (minus the gravity) that displays where the object is going to hit a wall, and show what angle it will ricochet at: (Pardon my drawing skills)
I have this system working fine on the technical side, all except for the fact because the raycast is endless, so the actual result looks like this:
So to be clear, in the end, I want the 1st raycast to go out infinitely until it hits something, and then when it generates the 2nd second raycast where the first one hit somthing, have the second raycast only go out a pre-specified distance (Maybe 3f or something like that), or until it hits something, in which case it should stop.
My Script:
Transform firePoint;
void Update
{
DrawPredictionDisplay();
}
private void DrawPredictionDisplay()
{
Vector2 origin = firePoint.transform.position; //unity has a built in type converter that converts vector3 to vector2 by dropping the z component
direction = firePoint.transform.up;
float radius = 0.4f;
RaycastHit2D hit = Physics2D.CircleCast(origin, radius, direction);
// Draw black line from firepoint to hit point 1
Debug.DrawLine(origin, direction * 10000, UnityEngine.Color.black);
if (hit)
{
origin = hit.point + (hit.normal * radius);
Vector2 secondDirection = Vector2.Reflect(direction, hit.normal);
// Create second raycast
RaycastHit2D hit2 = Physics2D.CircleCast(origin, radius, secondDirection);
if (hit2)
{
if(hit.collider.gameObject.tag != "Destroy")
{
// Enable prediction points
for (int i = 0; i < numOfPoints; i++)
{
predictionPoints2[i].SetActive(true);
}
// Calculate reflect direction
Vector2 origin2 = hit2.point + (hit2.normal * radius);
// Draw blue line from hit point 1 to predicted reflect direction
Debug.DrawLine(origin, secondDirection * 10000, UnityEngine.Color.blue);
}
}
}
}
Vector2 predictionPointPosition(float time)
{
Vector2 position = (Vector2)firePoint.position + direction.normalized * 10f * time;
return position;
}
Vector2 predictionPointPosition2(float time, Vector2 origin, Vector2 direction)
{
Vector2 position = origin + direction.normalized * 10f * time;
return position;
}
Notes:
While I would use regular raycasts, I found that normal Raycasts don't cut it because the raycasts are only 1 pixel wide and the object is (about) 512px by 512px, meaning the object would physically touch the wall before the raycast did, causing inaccuracy.
I've already created a system that generates dots along the raycast path in a similar vein to Angry Birds so that the player can see what the raycasts are doing in the game view, but since it's not relevant to the question I removed that part of the code from my script above. Which means all I need to do limit how far the raycasts go, not find a way for the player to see what's happening. (I'm addng this in the notes to avoid bringing up the conversation of whether or not the player can see what's happening.)
firepoint
is the barrel/tip of the weapon that the projectile is fired from. (The weapon rotates according to/following to the mouse)
Upvotes: 1
Views: 2510
Reputation: 4061
You can draw the line/path after you know if it hit an object or not:
Vector2 origin = firePoint.transform.position; //unity has a built in type converter that converts vector3 to vector2 by dropping the z component
direction = firePoint.transform.up;
float radius = 0.4f;
RaycastHit2D hit = Physics2D.CircleCast(origin, radius, direction);
var firstPathStart = origin;
var firstPathEnd = origin + direction * 10000;
if (hit)
{
origin = hit.point + (hit.normal * radius);
firstPathEnd = origin;
Vector2 secondDirection = Vector2.Reflect(direction, hit.normal);
var secondPathStart = firstPathEnd;
var secondPathEnd = origin + secondDirection * 3f;
// Create second raycast
RaycastHit2D hit2 = Physics2D.CircleCast(origin, radius, secondDirection);
if (hit2)
{
if(hit.collider.gameObject.tag != "Destroy")
{
// Enable prediction points
for (int i = 0; i < numOfPoints; i++)
{
predictionPoints2[i].SetActive(true);
}
// Calculate reflect direction
Vector2 origin2 = hit2.point + (hit2.normal * radius);
secondPathEnd = origin2;
}
}
// Draw blue line from hit point 1 to predicted reflect direction
Debug.DrawLine(secondPathStart, secondPathEnd, UnityEngine.Color.blue);
}
// Draw black line from firepoint to hit point 1
Debug.DrawLine(firstPathStart, firstPathEnd, UnityEngine.Color.black);
You can make a class to store the path information (how many segments does the path have, where each segment starts and ends), populate when you check for collisions and draw it at the end.
Upvotes: 1