Hi. Im having trouble getting the exit point of imaginary ray.
I have a proyectile which impacts against a spaceship (3D) and if gets heavy damage i want to show a explosion geting out from the contrary direction of the impact.
I use OnColliderEnter(Collider col) from the proyectile, to get the contact point (the red point, see image A.png) which is col.contacts[0].point. I need the yellow point. I thought in raycasting the target collider col.collider.Raycast() with a ray from away against the contact point. But for it i need the direction vector (the green arrow).
Im tried doing something like this:
Vector3 _direction = (col.contacts[0].point - transform.position).normalized;
Vector3 _away_point = col.contacts[0].point + _direction * 1000f;
But i get weird directions, see second image. I think its because trasform.position is modified after the impact is done (so the proyectile bounces and changes its position) but before OnCollisionEnter is called. Im tried with transform.forward but its the same problem
Its the complete code:
Vector3 _direction = (col.contacts[0].point - transform.position).normalized;
Vector3 _away_point = col.contacts[0].point + _direction * 1000f;
Ray _ray = new Ray(_away_point, -_direction);
RaycastHit _rh;
if(col.collider.Raycast(_ray, out _rh, 1500f))
{
//_rh.point is the needed point
//i need too the direction so i can assign it to the efect
}
Good question!
I don’t think the information you have in front of you currently is enough to figure out this information so what else can we know…
It sounds like your bullets are using physics and therefore will have rigidbodies on them, so we can get the rigidbody off the collider’s gameobject which has access to it’s physical state including things such as velocity.
Now given the point at which the bullet hit and it’s velocity - which is a vector direction - we can go about figuring out where the other side of the space ship would be. Instead of trying to find a way to raycast through the ship and find the point at which we leave it, this will be a lot easier if we raycast from a point far enough the other side of the ship pointing back in.
Say ships can’t be any larger than 20 units / meters:
private Vector3? FindBulletExit(Transform hitObjectTransform, Vector3 bulletHitPoint, Vector3 bulletVelocity, float maxObjectSize = 20)
{
// hit object transform is the ship itself
// max object size is how far we're going to start our ray, from the bullet hit point
Vector3 rayOrigin = bulletHitPoint + bulletVelocity.normalized * maxObjectSize;
// we start our ray in the direction of the velocity, at distance specified by maxObjectSize
// it's directed in the opposite direction to that in which the bullet was travelling
Ray ray = new Ray(rayOrigin, -bulletVelocity);
// your IDE might tell you to refactor this to the non-alloc version
// this will only happen once a ship's lifetime so not much gain but no harm in doing it
var bulletExitPointHits = Physics.RaycastAll(ray);
float closestHitDistance = float.MaxValue;
int closestHitIndex = -1;
for (var index = 0; index < bulletExitPointHits.Length; index++)
{
var raycastHit = bulletExitPointHits[index];
if (raycastHit.transform == hitObjectTransform)
{
// this hit has hit ship, is it the closest?
float hitDistance = (raycastHit.point - bulletHitPoint).magnitude;
if (hitDistance < closestHitDistance)
{
// if yes, set this as new closest
closestHitDistance = hitDistance;
closestHitIndex = index;
}
}
}
if (closestHitIndex == -1)
{
Debug.LogError($"FindBulletExit could not find opposite side of object {hitObjectTransform.gameObject} at {maxObjectSize}m from hit");
// if none of our hits hit the transform we specified we'll have to return null
// make sure you handle this possibility where you call this code
return null;
}
// this is the point on the other side of the gameobject
// the direction of the explosion will be the same direction as the bullet velocity
return bulletExitPointHits[closestHitIndex].point;
}
We use RaycastAll instead of Raycast because there might be multiple points at which the line running through your object might re-enter your object. Such as if there was a large barrelled gun on your ship, you wouldn’t want the exit explosion to come out of the barrel, rather the hull which will be the closer hit.
I haven’t tested this code, half because I am lazy and half because it’s there for you to see the process. If you’re struggling to debug problems involving vectors and directions, I don’t blame ya, humans aren’t all that good at looking at 3 floating point numbers and figuring out how that relates to another set of 3 floating point numbers in 3D space. SO unity give us the ability to write our own gizmos. Just like you have Start, Awake and Update - monobehaviours also provide functions called OnDrawGizmos and OnDrawGizmosSelected which allow us use of the Gizmos library. From here you can draw cubes, spheres, lines, etc that will show up in your scene during edit / play mode. Seeing the intensions of your code in actual space is so damn useful when writing any code like this - if the code doesn’t work then use these to solve it!
Im resolved it by using a coroutine like this:
private IEnumerator asd()
{
while(true){
_previous_direction = transform.forward;
yield return null;
}
}
It seems to save the direction before physics, but im not sure if always. And every proyectile will have one more coroutine running.
If anyone knows a better way please write