I have a AAA console gamedev background, so I’m used to having source access & I am finding myself immensely frustrated by what I can only describe as a missing feature in Unity’s rigidbody collision behaviour.
Physics engines typically work in several passes per update, broadly speaking:
update all objects in the simulation based on forces / accelerations / impulses acting on them this step
check for collisions
AFAIK all physics engines I have used have the concept of a ‘pre-solve’ collision callback/event - (i.e. after or during step 2 but before step 3). I assume that physx does, but couldn’t find the SDK documentation online to check.
Bullet - http://www.bulletphysics.org/mediawiki-1.5.8/index.php?title=Collision_Callbacks_and_Triggers#Contact_Callbacks
Box2d - http://www.box2d.org/manual.html#_Toc258082975
Having this event makes it very easy to detect all collisions but choose contextually on a collision by collision basis to ask the engine to ignore them (i.e. not to physically resolve them).
The important factor being that there are many gameplay reasons why for any given pair of objects the decision to ignore the contact, or not, might be based on information only available at the point that the contact is generated - i.e. immediately before the collision is resolved.
Assuming there isn’t a unity event for this (which I am pretty confident it isn’t as I have found no answers when I searched before writing this) then what is the “usual” workaround?
I’m anticipating some archaic combination of game objects having triggers that contain rigid bodies with colliders and additional logic, so would be very pleased if someone has an elegant solution
Just to be clear Alex … are you aware that it’s “not too late” to call Physics.IgnoreCollision in OnCollision???
Please launch the little project attached and run it.
Caveat - I’ve never really understood Physics.IgnoreCollision (perhaps because it’s totally undocumented, “when” it happens) but it seems to work in cases like that. This may or may not help you in some way.
This is not currently possible in Unity.
There are workarounds, but none let you handle the cases where an object collides with 2+ things in the same physics step, and needs to be affected in a custom way e.g. be stopped or moved or bounced using custom code.
If you save the velocity/angularVelocity/etc. from last FixedUpdate, you will have the data for the object before any of the collisions happened. OnCollisionEnter(2D) is properly called for both collisions (yay), BUT you don’t have much info about what happened. You have the circumstances, like the collision normal, the separation/distance, contact point(s), but you don’t have data for each object, like position and velocity/direction before and after the collision, or how far into the physics step the collision occurred.
Even if you did, you cannot simply roll back the object to the collision point, and do some custom bounce-code for each collision, because when you change the behaviour/result of the first collision/OnCollisionEnter(2D), then the data for the second collision/OnCollisionEnter(2D) call is made invalid.
To handle 2+ collisions in a single physics step, you only have two choices, really:
React to the first
OnCollisionEnter(2D) call for each
physics step, and do any further
collision detection for this physics
step manually…but you may have seen
the problem with this…any other
object in the scene will not have
been rolled back to its previous
position. You will have to roll back
every object, and manually do
detection updates. That’s a LOT of
code and a LOT of CPU cycles.
Turn down the Fixed Time Step
variable, even though that only makes
the problem less frequent.
That gets us down to 0 possibilities to fix this problem.
The workaround isn’t that convoluted: always store the velocity/angular velocity/position from the previous physics frame, and after a collision, if it’s not desired, just restore the velocity etc. so it continues on as if nothing had happened.