While optimizing audio performance of our game Human: Fall Flat, I’ve noticed quite big GC allocations in Physics.Contacts. It leads to GC collect once a second, potentially skipping a frame in a game. I noticed this a while ago in other project on Windows Phone and thought it’s WP specific. I believe this is related to allocating contacts array before passing to monobehaviors if no OnCollisionEnter/OnCollisionStay methods are defined it does not happen.
Human will feature a physics based audio and we need to get collision information which is later processed to drive audio events. Already heavily optimized the code inside OnCollisionEnter and OnCollisionStay, but this GC issue is outside my code.
We have one more GC allocation in GeometryUtility.CalculateFrustumPlanes but it’s only 136B per frame, still it would be nice to have and overload where we could pass existing array.
I had a small discussion with x.com (don’t know his forum handle) on alpha about this and he says there are plans. You can probably poke him on twitter to see if he wants to talk about it - he’d probably enjoy a stress test scene to work with…
This is a pretty huge issue, it makes OnCollisionStay almost unusable. Is there any news on this?
We just got NonAlloc versions of RayCastAll etc., it would be really great if we could get a NonAlloc version of OnCollisionStay, at the moment the garbage generated is just too much.
Another big improvement would be if we could call OnCollisionStay on demand or selectively instead of all the time.
I can tell you that the 2D physics system has had this resolved for non-allocating callbacks for a while (since last year). Part of that work (retrieving contacts in a non-alloc way) is in the 2D experimental preview about to be released. The problem right now is that there’s a change to the callback/event system that is holding this (2D) work up and the development of the 3D side of things as well. Essentially we can’t change existing callbacks and/or introduce new ones until this work has been completed.
Unfortunately, this is outside of the control of the physics teams right now but we’ve recently been into meetings to get this road-block resolved. It’s a super important thing to resolve for both 2D and 3D that we’re pushing hard against.
Anthony and myself are well aware of the issues this is causing and want to get the new system in-place ASAP.
Thanks guys, it’s a nightmare trying to raycast reliably when OnCollisionStay has everything we want, and it can be solved but it just isn’t
Often enough it’s just one contact as well, we don’t need many, but we need new data every fixed update… Seems crazy such a simple matter renders …Stay() unusable.
It’s two things that’s causing this; the first is that the Collision(2D) type is a class and not a struct and the contact-points, whilst a struct, is within an array that needs to be created. Both of these end-up as garbage.
We can’t just change the Collision2D to be a struct as that would break backwards compatibility. There are plans to introduce a new callback that offers much more utility and passes back a new (struct) type with no allocations etc.
That sounds brilliant for all our projects (we use 2D and 3D physics, spending on title). I hate to ask but would it be possible these (3D and 2D) changes make it in before Unity 6?
That sounds good, thanks for the update. Personally I am working with 3d, and as hippo said the ability to limit the contact points stored on every call would be very useful as well.
Non allocating struct sounds perfect. Really looking forward to the new callbacks.
There are still ‘Physics2D.ConvertCollision2DForScript’ GC allocations showing in the profiler in 5.6 and 2017.1.0b3 if you implement OnCollisionEnter2D. There is a screenshot of the profiler in this thread. Physics2D Collision Garbage - Unity Engine - Unity Discussions
Also note that I did have a branch which completely rewrote the 2D physics handling and removed all GC activity (as I stated above) however it made changes that were not allowed (yes, Unity is big and things need to be validated and everything needs to work together). I ended-up putting all the contacts rewrites in there but without the new non-GC contact callbacks. If it were simple then it’d be done already.
That work was on hold until “another system” was implemented. It has been frustrating as that other system has still not surfaced and my hands are tied. I recently made a push to get this resolved and as I posted in the thread above, we’ve got a meeting to discuss the next step for this which has to happen soon.
The scripting backend has seen much love recently and AFAIK, we’re ready to move forward with a new super fast event system. This’ll not only solve the GC issue but also make script callbacks much faster.
When I was testing my multithreading 2D physics work where I had half a million collisions being processed, by far the most dominant portion was the script callbacks. I ended-up disabling those completely just so I could work correctly. This is another aspect that should be solved.
If we didn’t care about backwards compatibility then we could just change “Collision” and “Collision2D” to be structs and not classes. That combined with the lazily created “contacts” property (which you should not use) and the new “Collision2D.GetContacts()” would mean zero GC activity.
Users don’t really care about excuses, but we do need to make hard decisions that will affect our development schedules. In this case, I don’t have much confidence that it will ever get fixed. It’s unfortunate because this is the only GC in my game, i am sure others are in the same boat.
I am also sure that we would be ok if you bypassed the backwards compatibility excuse and made parallel API, like the raycast stuff, something along the lines of OnColisionEnter2DNoAlloc().
Excuse? You mean reason right? If you want to negative-spin it then sure, lame excuses.
All I can give is transparency on what is currently happening as I always have. We all have dependencies on something. If this is not good enough for you then there is little else I can do. I could’ve easily not provided you with the information despite your tone but I am here doing what I can do given the restrictions. There is frustration on both sides.
Whilst that might sound good for you, it’s not something that can just be thrown out there. Unity is undergoing a lot of changes with major refactoring under the hood and removing tech-debt is extremely important. The physics callbacks are tech debt and require the new fast event-based system in-place before we can remove it.