New contact dispatch for physics

Hello,

We’ve been cooking up a new way to read contacts for Physics and I’d like to share a preview build and the upcoming functionality. Currently the main way of retrieving contacts is through OnCollisionEnter, OnCollisionStay, and OnCollisionExit methods on MonoBehaviour scripts which are slow and sometimes inconvenient but seeing the success of the Contact Modification API we decided to mimic it, and expose a similar event for regular contacts. The main advantages of the new way is speed and possibility to jobify the code if that is desired.

In the preview build you’ll find 2 new events. Physics.ContactEventStart and Physics.ContactEventEnd. They are both called on the main thread. The ContactEventStart could be either used to schedule some jobs for the contacts or to process everything on the main thread. The ContactEventEnd is for completing the jobs or disposing native containers as the NativeArray from the first event will become invalid after this event is finished. Another important difference between the old and new ways is that the contacts are reported before transforms are synced! I’m attaching a small project with a few sample scripts that uses the new API.

All of the Collider components now contain a property called “Generates Contacts” which determines whether or not that Collider generates contacts in PhysX. If the property is set to false, but the Collider has a MonoBehaviour script with the OnCollision{Enter/Stay/Exit} methods, it will still report contacts.

The old system can be completely turned off in the Physics tab of the Project Settings window by toggling the “Report MonoBehaviour Contact Events” option. No MonoBehaviour methods regarding contacts will be invoked but they will still contribute to raising the contact generation flag as mentioned above.

The first part of OnCollision{Enter/Stay/Exit} reporting process has been sped up using this new approach so already existing code should see a moderate performance boost as well.

If you’ve got any questions or suggestions/ideas on how to improve the new API, please don’t hesitate to share. Using these posts to shape upcoming functionality before it’s officially shipped has been a great experience in my opinion and all the feedback is very appreciated.

Link: https://beta.unity3d.com/download/7335c5627d40/public_download.html

P.S. All the API naming is subject to improvements :smile:

7970691–1022472–ContactEventDemo.zip (191 KB)

19 Likes

Thank you for this! It’s a great improvement, for sure!

I don’t get this entirely. Does this mean that a MonoBehaviour with OnCollision{} methods still receive the OnCollision{} calls even with this option toggled off, as long as its collider have the “Generate Contacts” flag enabled?

Also, does this option have a corresponding Physics.{someProperty} in the Physics class we could read and write in runtime?

Given the widespread usage of OnCollision{*} methods I’m not sure if exposing this option in the Project settings makes sense, as disabling it would break nearly any project, package or script that uses physics. The old current system cannot be deprecated anytime soon. Does disabling it involve a significant performance gain, or has some other relevant advantage?

It might also be a good time to take a look at this bug (Case 1395187), where contact calls aren’t generated in child non-trigger colliders when they contact other triggers:

Hi!

  1. No, when the toggle is off, those OnCollision{*} methods will not be invoked.
  2. Yep, there is an exposed C# property that can be toggled at runtime. Which I now realise I forgot to make public in this build :frowning:
  3. Maybe me calling the OnCollision{*} system “old” is misleading, sorry. We are not deprecating it, but disabling it has a major performance boost. The toggle is set to true by default but I imagine for some specific projects turning it off could be beneficial.

Taking a look at the linked thread.

Thanks for the replies! Time for a new build then :slight_smile:

That’s a very valid reason!

Then I’d suggest throwing a warning in the console for each script that contains OnCollision{*} calls when this option is disabled. Users could then realize of which scripts won’t work properly if they disable this option, so they could perform the proper actions.

Edy,

This is an early preview and things can change, but here is a rough plan for this:

  1. Expose a way to read contacts from C# such that we only pass a native pointer to a buffer (a-la contact mod).

  2. Can we make it so that the OnContactXXX events are a result of C# code working on the native buffer and not a result of C++ code receiving stuff in a callback and then calling SendMessage on each pair?

  3. Threaded fetch contacts.


That said, we don’t aim to break compatibility with shipping this feature. If we can work out (2), then OnContactXXX becomes faster generally, and probably more flexible too. If we can’t, there would be a (set of) property to enable the fast track with the new API while also making sure the old stuff works.

Generally speaking, this change is part of a larger initiative to enable the next generation of behaviours & cases for both games and robotics: articulation body, contact modification, fetch contacts, access/create low-level shapes, immediate mode – and more, all within the GO+PhysX framework, so that all of your old code doesn’t have to be thrown away.

Hope that makes sense.

Anthony.

6 Likes

It really makes sense, thank you for the detailed update Anthony. Really good to know the general plans on these aspects.

Hey, sorry for the silence. Couldn’t publish a public build due to issues with our build system. Here’s what happened with this feature in this time:

  • Physics.ContactEvent is now raised after the Transform sync, just like OnCollisionXXX messages.

  • Jobs scheduled in the Physics.ContactEvent now must be completed before the next Physics.Simulate() call, be it internal or manual. Which in all cases gives more time for the jobs to run freely without blocking the main thread.

  • Because of the point above, Physics.ContactEventEnd is now gone.

  • Data layout of the new contact callback has been greatly simplified and there are a lot less redundant and confusing methods now.

  • All the data structs are now readonly but can be acquired as safe C# references via readonly ref keywords removing the copying cost.

  • As Anthony mentioned, OnCollisionXXX callbacks are now called from C# and are ~30% faster in tests that I conducted.

  • Physics.reportMonoBehaviourContactEvents is now actually public and can be beneficial when only the Physics.ContactEvent is used to read contacts in a project as this will stop the physics system from iterating the simulation results to find who wants the OnCollisionXXX calls.

Here’s a link to a new build: https://beta.unity3d.com/download/847d26562703/public_download.html and an updated version of the previously attached little sample project

8040407–1037177–TestContactEvents copy 2.zip (190 KB)

7 Likes

I forgot to post an update, but this feature has landed and should be publicly available in 2022.2.0a15 and newer.

4 Likes

Thank you, I need this for Piecewise Equations of motions for objects colliding against each other. Application is purely educational.

I will upgrade 2022.1.0b14 to 20221.2.0a15 to use it. Thank you

Dara

Disclaimer: None of the presented materials by any stretch of imagination were meant to Advertise nor Spam any Unity organization. Nor meant to solicit business from anyone at Unity nor its customer base. Materials are solely meant for non-commercial Work-In-Progress presentation.

Awesome.
Now callbacks can get from child colliders:

Simple example: