- Home /
How can the resultant velocity of an object after a potential collision be predicted?
I'm creating a game with a mechanic similar to Peggle. I'm launching a small spherical projectile at a capsule. The rigidbodies of the objects are constrained such that the collision is effectively 2D (just two circles colliding). I want to calculate the direction the projectile will be heading after the collision.
Currently this is my process:
Call
Physics.SphereCast
along the path of the projectile.Reflect the projectile velocity about the
RaycastHit.normal
vector.Place an arrow object at
RaycastHit.point
facing the direction of the reflection vector.
Here's the relevant code (the projectile is launched from the origin):
var raycastHit:RaycastHit;
if(Physics.SphereCast(Vector3.zero, radius, projectileDirection, raycastHit, range)) {
arrow.position = raycastHit.point;
arrow.LookAt(raycastHit.point + Vector3.Reflect(projectileDirection, raycastHit.normal), Vector3.up);
}
With this method, I'm having two problems:
The arrow direction is not accurate (as much as 15 degrees off).
Physics.SphereCast
detects collisions that the actual projectile never hits (the radius of the sphere collider and the radius parameter passed toSphereCast
are the same).
I have a hunch that this means the actual physics calculation is done differently than I am doing it here (which is the typical "reflect the velocity vector around the contact normal" model). What I need to know is: how can I more accurately predict what the result of the collision is going to be, preferably without writing physics code myself?
Answer by aldonaletto · May 27, 2011 at 12:39 PM
I'm not sure, but I suspect the raycasthit.normal is the normal of the triangle hit, not the normal at the collider's surface - it could explain the inaccuracy. Since things are limited to a plane, I think it's better to calculate yourself the direction: create a line equation for the vector projectileDirection and a circle equation for the cylinder, then replace x and y in the circle equation and find the intersection points - it's a quadratic equation, so you usually ends with two points; the nearest one is the contact point. With the contact point, calculate a line from this point to the center of the cylinder - that's the normal line - and reflects the vector projectileDirection along this normal... A piece of cake, no? Don't panic! You can find the equations in:
http://mathforum.org/library/drmath/view/55134.html
If you need some additional help on this, let me know and I'll try to help you.
I should have said this: the cylinder is modeled by a capsule collider.
I found an error in your script (and in my apprach too!): the sphere has a radius, while the ray has none, so the point the ray hits de cylinder is not the same the sphere would hit. Since both are circular objects, you can expand the collider radius of the cylinder to the sum of the cylinder and sphere radius: the ray hit point at this expanded cylinder will be equal to the sphere center during collision, but the normal will be correct if you use a cylindrical collider (or a long capsule to assure the ray hits the cylindrical part). Let rS and rC be the sphere and cylinder radiuses: try to set the collider radius to rS+rC, do the raycast and return the collider to the previous dimensions. The actual hit point can be calculated with something like this:
hitPoint = (cylinder.position-raycasthit.point)*rS/(rS+rC); hitPoint.y = sphere.position.y;
I'm presu$$anonymous$$g your horizontal plane is XZ, it's really horizontal and the sphere is running on it like a billiard ball.
I did some tests, and the results were very interesting. I tested several colliders attached to a rotating object. I cast a ray perpendicular to its center, and drew another ray in the normal direction, originated at the hit point. The capsule collider was the craziest one: the normal swung in the horizontal plane (the plane perpendicular to the capsule axis) in a small angle, probably the 15 degrees you've mentioned, but swung in a bigger angle in the vertical plane! Forget it!
Box and mesh colliders behaved as expected, with the normal swinging in the horizontal plane but not in the vertical, and the sphere collider was perfect: the normal stood still all the time.
One solution I can think of is to use a sphere collider with the cylinder radius, but centered in the same plane as the projectile center. It would give accurate results, I believe, and could even be used in the collision itself - provided all projectiles have the same radius and stay in the same plane.