- Home /
Velocity data from OnCollisionEnter is delayed (incorrect)
I'm trying to do damage calculations between game objects on a collision. The damage will be based on the velocity of each game object during the collision. The problem is that the velocity data seems to be delayed. In other words, the velocity for each object that I read during OnCollisionEnter is the updated velocity shortly after the collision. As a test, I did the following:
BEFORE COLLISION
Object A is stationary -> velocityA = (0, 0, 0)
Object B moves directly towards Object A -> velocityB = (0, 0, 32)
CODE DURING COLLISION
void OnCollisionEnter(Collision collision){
// Get initial data
Vector3 theirVelocity = collision.rigidbody.velocity;
Vector3 myVelocity = collision.relativeVelocity - theirVelocity;
Debug.Log ("My velocity: " + myVelocity + "\tTheir velocity: " + theirVelocity);
}
I would expect that the 'Their Velocity' value would be (0, 0, 0) because they were stationary right before the collision, but instead their velocity is (0, 0, -10.6) which is what their velocity is directly after the collision. I also tried this using collision.rigidBody.velocity, but that returns the same value.
One thing I noticed is that if Object A is against a wall or in a corner when I hit it, the 'Their velocity' value does return (0, 0, 0). I assume this is because Object A has nowhere to go and therefore Object A's velocity doesn't actually change from (0, 0, 0).
Is there a way to get the velocity data of each game object directly before the collision takes place?
Answer by MacDx · Dec 18, 2017 at 10:37 PM
Yes, there is a way. You need to save the velocity during fixed update. If you take a look at Unity's Execution Order in the Physics section, you can see that there is an Internal physics update, this is where I think every rigidbody is moved, and every velocity is updated as a result of collisions, then, after that physics update comes OnTrigger on Collision and Coroutines waiting for fixed update, that is why you are getting the affected velocity and not the one before the collision. Like I said if you want velocity before collision, you will need to have a field on your script where you will save the velocity every Fixed Update. Something like this:
private Vector3 velocityBeforePhysicsUpdate;
void FixedUpdate()
{
velocityBeforePhysicsUpdate = rigidbody.velocity;
}
So when you check velocityBeforePhysicsUpdate inside your OnCollision or OnTrigger methods, the field should contain the velocity you're expecting.
Hope this helps!
Worked like a charm thanks! I'm going to take a look at that Unity docs sections, thanks for the link.
Answer by lennardbeers · Feb 26, 2019 at 02:46 AM
@MacDx Hey, I know this is old, but i have a question. The solution above works, but it is very performance unfriendly. I don't want to save the velocity every physics frame, I only want to save it, when the object is actually colliding. Does anybody have an idea how to achieve this? I looked into every forum question about this topic, but nobody seems to have a better solution than just bruteforcing it. This can't be the only way :(
@andcl85 I fixed this problem and the many others I had with the Unity integrated Physics and Collision by simply not using it at all and doing custom collision detection + physics. If the Unity rigidbody physics don't work for your particular case I would recommend you do the same. It's much less work and you don't spend all your time trying to find workarounds. I only use the FixedUpdate() method to apply my calculated position to the transform and after that check for collision myself with simple circle or rectangle collision mathematics. This works especially good for me, because I only have three GameObjects that can collide at all in my game.
are you making a game similar to ping-pong?
I actually needed this for a clone of the old school game Blobby Volley.
Answer by beckermt · Mar 08, 2021 at 10:04 PM
@lennardbeers I found a solution for my particular case. I set my colliders to be triggers and used OnTriggerEnter2D instead of OnCollisionEnter2D. I suppose the trigger triggers before the collision does! :-)
Your answer
Follow this Question
Related Questions
Is it possible to tell Unity physics to ignore a collision at collision time? 1 Answer
OnCollisionEnter: collision.gameObject has weird behaviour 0 Answers
Excluding some physics collisions 3 Answers
Detecting When Intersection Penalty is Being Applied 2 Answers
Do you have to have a rigidbody component for collision detection? 1 Answer