tl;dr - here is a custom build with the experimental contact modifications API exposed: https://beta.unity3d.com/download/7a80bceabf9d/public_download.html. It is based on 2020.2.a8 and only the mac, windows and linux editor executables are available at this moment in time.
Contact modification is all about customizing the reaction to contacts, and that has been a rather frequent request over the years. PhysX offered this functionality a while ago, but just because of the internal implementation details it was tricky to expose it to scripts in Unity. Today I wanted to share with you a custom build with some early/experimental work in that area, to see what you guys think. In spirit of transparency, let’s look at this together and shape it to a form that is shippable and usable (just like we did with Physics.Simulate, articulations, PhysX upgrades and many others).
This demo shows two use cases actually. On the left a ball falls through a plane by ignoring all the computed contact points. This can easily be extended to ignoring a portion of a mesh (make holes in anything). On the right, there is a bouncy cube that reflects off tilted planes. It doesn’t rotate because all the contact points are ignored but one. This only contact point is set at the centre of the cube, so the depenetration impulse won’t cause rotations. The target velocity is also set to communicate the desired direction of the bounce (along the plane normal).
Let me know what you think. Thank you so much for testing and sharing your ideas.
That’s cool thanks!!
As per this update, will the regular ContactPoint struct expose the individual impulse for that contact? (instead or in addition to the aggregated Collision.impulse). It think it’s a good opportunity to improve that, and would be useful in more situations.
What I have in mind next is to try exposing a buffer of contacts to scripts, for direct iteration by analogy with modifications. Essentially, an approach that would allow to iterate an array of PxContactPair and access directly what’s there with no wrappers. Traditional contact callbacks can easily be achieved from there. I believe there is still a lot of overhead with the current per-pair callback design that is driven by the native code.
I quickly looked at the demo project and current API.
What I do wonder a bit is this:
public void ModificationCallback(IntPtr buffer, int count)
{
for (int i = 0; i < count; ++i)
{
var header = ModifiableContactPairHeader.GetFromBuffer(buffer, i);
If one uses contact modifications, you are more than likely to iterate through all contacts. At least I can’t think of any exception where this wouldn’t happen. I do know that you’ve exposed this in pretty similar manner to how physx does it though (they don’t expose the whole buffer natively at once either if I remember right). But what I’m wondering is if Unity could just grab the whole header array in native code and pass it all once to managed side? I dunno what kind of overhead difference we are talking about here but just throwing it out there as this could result in better perf with lots of modifiable contacts.
also bit curious about this:
// This should be done once before every physics simulation, for now.
Physics.SetContactModificator(contactsReceiver.ModificationCallback);
would this be done automatically in final version if contact modifications are enabled (I feel there should be a physics setting toggle for this that’s set to disabled by default so you could omit this for projects that don’t need it). I’m curious what extra is currently done on each fixed update for these? You’d think this could be just registered once on level load?
I was also going to point out the need for collider specific flags (as physx supports this) but I then saw mention of this already on the google doc you linked
Also wondering a bit about the naming, for example ModifiableContactPairHeader seems bit too verbose for my taste, could it be just ContactPairHeader?
All in all, I’m happy to see that you managed to expose all the contact mod api here, looking forward to the day this works on stock Unity
Also, any chance to get next preview on 2020.2.0a15+ so we could test this with new articulation additions?
As additional note, I’d love to see new physics features just get merged to main releases sooner with (Experimental) tags, just like happens with new rendering feats atm. This would give people early access to new things and more time for Unity to stabilize the feat / API before locking it in. In case of contact modifications, it would be a pretty safe addition as long as there’s a physics setting that sets the whole feat off by default
As second additional note, this isn’t really that big of a deal but there could be an additional toggle for contact modifications when you create additional physics scenes (this is getting into super niche category) but I’m guessing this wouldn’t be that difficult to implement as the contact mod callback is set on physics scene creation, could just throw this into the mix. What I mean here is that if you have multiple scenes with different physics scenes, you could opt to only have contact mods enabled on some of them.
Yes, I’ll do that once I’m back to work in mid-August.
I’m not sure I follow 100%. Isn’t the current API exposing everything you talk about, just not in a flat array? It’s a flat array of contact pairs, each having a link to a flat array of contact points, essentially.
This is a great question, thanks. The way I imagined this (not verified yet!) is to expose a sort of a function that marks a collider as having modifiable contact points. Something like Collider.modifiableContacts = true. Collider already belongs to only one scene, so we’re done with that on this side of the API. Then, it’s one callback invocation per scene actually. But you’re right I should probably extend the callback so that it accepts the scene reference explicitly.
[quote=“yant, post:8, topic: 798637, username:yant”]
Yes, I’ll do that once I’m back to work in mid-August.
[/quote]Thanks, will keep eye on the thread
[quote=“yant, post:8, topic: 798637, username:yant”]
I’m not sure I follow 100%. Isn’t the current API exposing everything you talk about, just not in a flat array? It’s a flat array of contact pairs, each having a link to a flat array of contact points, essentially.
[/quote]Ah the point wasn’t that something wouldn’t be available, the suggestion was mainly to reduce the interop overhead if you could just pass the whole array at once (as NativeArray etc). This could play a role if there’s a lot of contacts to process (again haven’t tested the perf but it’s pretty hard to properly test on editor).
[quote=“yant, post:8, topic: 798637, username:yant”]
The way I imagined this (not verified yet!) is to expose a sort of a function that marks a collider as having modifiable contact points. Something like Collider.modifiableContacts = true.
[/quote]This would be fine IMO considering how niche this feat ultimately is.
Awesome stuff! Isn’t contact modification how you’re supposed to implement the modern versions of triggers in PhysX? Would this open the door to more robust and performant triggers in unity?
I don’t think you should do triggers as generic solution with this. Contact modifications do have perf overhead applied to them so you should use them sparingly, they are more like special hammer to fix edge cases and things that are known to cause issues with generic contact solver data.
Also worth noting that the way this works, you are supposed to mainly alter the contact data, not generate extra events from it (but surely you can also extract a lot of extra data with it, just be aware of the lack of Unity api while using the callback). Doing triggers with it is technically possible but I doubt you could make them more performant this way.
Of course if you need more functionality that is not available through existing API, this could allow you to hack your own variants.
Yant and Pierre Terdiman discuss it in this thread, apparently the built-in trigger path in PhysX is both janky and slow. https://discussions.unity.com/t/733475 page-3
but i vaguely remember another thread talking about it where they said filtering was faster, but i haven’t been able to find it. Unreal engine actually implements their triggers this way and it lets them do some very detailed collision filtering, for example letting a shape collide with one layer and just overlap (their version of trigger) against another layer.
If you have done any experiments on this, i’d love to hear about them, i haven’t messed with internal physX myself in years. =3
@Cynicat You are correct that Unreal doesn’t use trigger path at all but their approach also has it’s own overhead. I should double check but pretty sure they do manual polling for final overlaps there which in turn creates x amount of extra steps to accomplish this. It is probably what allows them to do their filtering setup like they do though. Their huge overhead from the overlap checking is reason why you should always omit them in Unreals actors if they don’t need it (these used to be enabled by default for each actor there in past but I think they changed the default at some point at the expense of convenience of overlaps always triggering). But I do admit I have no idea if using trigger callback from physx is any slower or faster than doing it like unreal as I’ve never actually tested the different approaches on same framework (so I don’t even try to estimate this myself).
Anyway, to get back to the point. What Pierre suggested on that thread (afaik anyway) was to implement triggers same way as regular collisions but omit the few flags that make them resolve collisions. This is a different approach from omitting the collision from already processed contact pair data through contact modification api. Former (omitting those few flags from physics shapes) basically says to physx that this physics shape will not have it’s collision resolved so it never processes the relevant data for it. If you ignore the collision through contact modification api a bunch of extra things already get computed before you get to even ignore the collision. Contact modification is just the last step in the way where you can make final adjustments to the data before contact resolving happens.
I have doubts that contact mod api could help on generic trigger case but if you have special case that needs it or you just need it for few limited amount of objects, I guess it’s still possible to abuse the api a bit for this purpose. If just talking about this previews implementation, yant mentioned that Unity api is not available to use within the contact mod callback but you could probably cache the event data during contact mod callbacks and send it after physics.simulate is done etc to keep the thread safety intact.
Thanks for the details! I didn’t know most of this, i’ll trust your judgement and do more research then.
I’m desperate for reliable triggers in unity and will clutch at any straw I see. I’m so tired of bending over backwards and burning tons of perf just to keep track of what a trigger is overlapping. =<
Pierre and myself experimented with emulating triggers as contacts some time back.
Basically, generating the contact pairs, and then filtering them out after the broadphase. That was with the onContact call, not through modifications. I’ll have to recollect but there were some rough edges there actually, we couldn’t seamlessly migrate from onTrigger to onContact with no side effects. For instance, by default, the contact pairs won’t get generated for kinematic pairs, but trigger pairs would. Fixing that required turning on a potentially expensive option that enables all kinematic pairs to be processed. It’s all solvable potentially, but not directly and instantly. Just my 2c. Anthony.
It’s awesome to see that we’re finally on the cusp of getting this functionality, I’ve been wishing we had it for a long time now.
It definitely seems a little awkward for the API to expose a raw IntPtr and count instead of a more formal accessor. In the absence of support for Span, the above suggestion to supply a NativeArray parameter (and equivalents for the fields) seems like the natural choice to me, since it’d be far less error prone.
Also, this is a bit of a nitpick, but is there a reason for the API using “modificator” instead of “modifier” in its naming?