Pre-collision solver callback - why are we not talking about this?

Hello internet

I’m building a game with balls and walls and paddles (Pong, but crazy). I have coded custom bounce-physics for my paddles and walls. I apply these in OnCollisionEnter2D, by rolling back the ball to the point of contact, then solving the bounce into a new velocity, then move the ball the same length it had moved since the collision, along the new velocity vector. And it all works fine…

…until the ball hits two walls/paddles in the same physics step. OnCollisionEnter(2D) is properly called for both collisions (yay), but I don’t have much info about what happened. I have the circumstances for each collision, like the collision normal, the separation/distance and contact point(s), but I 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 I did, I cannot simply roll back the object to the collision point, and do some custom bounce-code for each collision (which is my current solution), because when I change the behaviour/result of the first collision/OnCollisionEnter(2D), then the data for the second collision/OnCollisionEnter(2D) call is made invalid (because the entire physics step has already been carried out). An even then, with only a single collision, my change to the velocity and moving the object, might put the ball inside a wall which it should have collided with.

Is it at all possible to implement a callback function in the middle of the PhysX/Box2D physics step, so I can change e.g. the velocity of an object during the physics step? Can we have an OnCollisionEnterPreSolve2D or something? Or maybe a custom Physics Material 2D, where I can put in some code to solve the collision? Or a better solution from someone wiser than I.

It has only been asked about a few times, but [consistently over the years]( We need a way to detect and resolve collision hits manually page-2).

Exposing some of the constants and functions was a great step, but if we’re stuck with Physic Material and Physics Material 2D for customizing bounce physics, the latter of which only has 2 settings, we’re never going to have fun Pong/Arkanoid games…unless people start coding custom physics engines…and we don’t want that.

1 Like

I would love this also. I believe box2d in it’s original form allowed you to assign custom functions for it to use for friction and collision. Why don’t all engines do this?

1 Like

Indeed it does, Antony.

If anyone is interested, here’s a very detailed run-through of how a collision is solved in Box2D, and here’s Erin (one of the creators of Box2D) telling a forum user about how CCD collision detection works vs discrete collision detection.

So, Unity developers, how come this key feature of Box2D hasn’t been ported?

I assume that Unity is using that feature themselves to allow box2d to work with their scripting callbacks and such, but that’s just a guess.

These callbacks are handled during a simulation step and so are not provided because we cannot control modifications to the simulation objects in the script callback (objects added, removed, changed etc) which would seriously break the simulation, even cause crashes.

We are working on a low-level implementation of the physics systems, utilising the ECS and C# job-system which will provide fine-grained control and access. The high-level GO/component set-up won’t expose this however.

Hello

Thank you very much for your answer.

So, if I’m reading this right, the new system you are working on won’t allow me this either? I understand that it may cause a lot of problems for the simulation, if someone were to mess with GOs in the wrong way during this phase. But I can already crash my game in several other ways, if I really want to. Box2D provides this functionality when using the stand-alone version. I guess I’ll have to make my Pong game in C++, then.

Man, this really saddens me, though. Just changing the velocity and angular velocity is all I need. But since it’s all or nothing, I guess we’re out of luck.

Thanks again for your answer. It is highly appreciated!

No, I said…

So yes, it’s low-level and you drive it all. Like using Box2D directly however it’s all in C# abstracted away from it and compatible with the ECS and C# job-system.

For the here and now though and because you’re not interested in what the solver does and want to implement your own collision response then have you not considered using a Kinematic Rigidbody2D (for the ball) with useFullKinematicContacts set to true and moving it using MovePosition? This means the Kinematic body produces contacts when contacting Dynamic, Kinematic or Static colliders. You can then simply ask for the contacts using GetContacts and implement your own solver to produce the appropriate collision response based upon those contacts. This is much faster than having expensive callbacks to scripts done on a per-contact basis. This way you get all the contacts in one go when you ask for them and can respond appropriately.

1 Like

Oh! Wow, that’s awesome! Good luck with the development. It’ll be a massive asset for your users!

I thought this:

…meant that I wouldn’t have access to it, but only Unity internally. Thanks for clearing that up!

Thank you SO much for sharing your insights about the system. I’m not sure it would solve my problem, though.

Small scenario, using the setup you described:

  • I use MovePosition() in my ball’s FixedUpdate()
  • My ball registers a contact with a wall
  • OnCollisionEnter2D is triggered (?)
    • I move the ball back to the contact point, caching the length it HAD moved since the contact (for simplicity; or calculate the elapsed time)
    • Calculate new directional-vector
    • Move the ball along this new vector, the cached length, again using MovePosition(), but this time inside OnCollisionEnter2D
    • My ball hits another wall during this MovePosition() call
    • OnCollisionEnter2D is triggered again (?)
      • Do the same steps as before…etc.

Is this how it would work? I really need this to work with handling several collisions per FixedUpdate().

But does this approach not also mean, that I will be moving my ball AFTER all the other objects have already moved and collided with each other, and thus I’ll be too late in reacting to their movements throughout the physics step?

In that case, I would have to set up all my moving objects in the same way as the ball, and do even smaller, manual incremental updates on all of them in the FixedUpdate() of my main loop, and handle collisions on them all throughout. This sounds like it’ll be essentially the same as just lowering the fixed timestep.

This looks amazing and it would probably solve all of the physics problems I’ve encountered in Unity!

I know you’re the 2D physics guy, but are you aware of any plans to give 3D physics an ECS-ified “Low level API” too?

And is there a “GetContacts” equivalent for 3D, or are we confined to the OnCollision() callbacks?

Would this approach not still limit me, to moving my ball AFTER the solver has completed for all other physics objects? My ball would not be able to interact correctly with any other moving objects, unless I solve those manually as well.

No matter what, I’ll still have the problem with my kinematic pads, since I only get to move them in FixedUpdate, after the solver…looks like I have to somehow tame a dynamic object to be a pad, and move it with forces, to get perfect responses, and wait until I am able to override PreSolve to get my custom bounce.

I know I’m picky…I just don’t see the point of doing a Pong game, if the physics don’t feel just right :slight_smile:

I have been watching the road map, and I was seeing that this was listed under development times long or uncertain, but now I see it nowhere on any roadmap. Has this been dropped, or is there still a plan to develop this?

1 Like

Has this been implemented? Iv’e been searching around and havnt found info in it. Maybe I’m not looking at the right places?

1 Like