- Home /
Accurate Position of Object on Collision
Hey guys,
Using collison points to attempt to spawn an object in the same position of an object at the collision.
void OnCollisionEnter(Collision collision )
{
foreach (ContactPoint contact in collision.contacts)
{
if(contact.otherCollider.name == "Sphere2" && CollisionOccurred == false)
{
SpawnPoint = contact.thisCollider.transform.position;
CollisionOccured = true;
}
}
}
Then go on to create object at SpawnPoint.
My problem is contact.thisCollider.transform.position; seems to be a position a couple of frames after the collision and this is really noticable if the collision is at high speed. Eg if the object hits the "sphere2" and 'bounces' to the left quickly, SpawnPoint is noticeably left of where the sphere actually was at the collision point. Accuracy is important for my project.
Anyone else had this? I can't even understand how this is possible.
Any suggestions on how to Spawn at the exact location of an object at collision accurately?
Answer by Kryptos · Apr 11, 2012 at 09:58 PM
This is not due to high speed (although the difference is much more visible in those cases).
The Collision
struct that you get in the OnCollisionXXX
methods contains data about the current state of the objects, i.e. after the collision. In fact, the physics system need several cycles to reach a stable state. Those intermediary states are hidden (and happen in a single FixedUpdate), only the stable one is returned.
Position of objects at the collision:
The best solution is to track the previous values of position/rotation, with something like:
private Vector3[] prevPosition = new Vector3[2];
private Quaternion[] prevRotation = new Quaternion[2];
void FixedUpdate()
{
prevPosition[1] = prevPosition[0];
prevPosition[0] = rigidbody.position;
prevRotation[1] = prevRotation[0];
prevRotation[0] = rigidbody.rotation;
}
Then prevPosition[1] and prevRotation[1] always contain the previous value.
Position of the average collision point:
Vector3 v3AveragePoint;
foreach( ContactPoint contact in collision.contacts )
{
v3AveragePoint += contact.position;
}
v3AveragePoint /= collision.contacts.Length;
Answer by Kleptomaniac · Apr 11, 2012 at 03:53 PM
If your collisions are occurring at high speed, comparatively, your foreach could take some time to iterate through every contact point. This could mean it takes that fractional amount of time too long to save the transform.position for the spawnpoint.
I'm not particularly sure how you could get past this, unless of course you were to use a trigger, in which case you wouldn't need to iterate through the contacts array.
Hope that helps, Klep