Much to my confusion and frustration, when I switched to Unity 5 on my current project I saw my physics performance get worse instead of better (which is not the result I’ve had upgrading other projects). As a result, despite only having 5 -10 rigidbodies in a scene at once, my physics cost is several milliseconds. Since I’m optimizing for VR those lost milliseconds are painful and this is dominating my frame’s CPU load when things get complicated.
My game is a space dogfighting sim with reasonably complex ships. An individual ship has some 20-40 colliders (which, for design reasons, can’t be simplified very much; I need the detailed hitboxes), which are also duplicated on a second proxy object for netcode/smoothing reasons. Despite the apparent complexity, these proxies only have a single rigidbody each and their layers do not interact with one another. The environments have collision geometry, but the projectiles from weapons are raycasts and aren’t part of the problem I’m trying to address as they show up in the profiler separately. Since the game is set in space, actual collisions between objects are extremely rare.
Under Unity 4, this setup had a very low CPU cost frame to frame, which makes sense to me given how few moving objects there are and how rarely they interact. However, now I’m seeing a large performance cost, primarily in Physics.UpdateBodies. I’m also seeing the physics profiler report a huge (400+) number of contacts despite nothing actually colliding. Experiments suggest that this is related to entering bounding boxes of other geometry, as I’m able to make those contacts go away by flying a ship far from any of the world geometry.
Anybody have any ideas why I’m getting poor physics performance? Did compound colliders just become more expensive or something?
I did make sure to verify that, yeah. The proxy rigidbodies and their colliders are on a layer that allows self-collision, but disabling that doesn’t change the number of contacts. Having those colliders as children of the same rigidbody should prevent that, I’d have been very annoyed if that wasn’t the case anymore!
As far as I can tell, the contacts are actually coming from entering the bounding box of other collision bodies. A single ship flying around the scene will have a bunch of contacts when next to (but not touching) environmental geometry, and those contacts will disappear if you get far enough away. I have no idea if those contacts are at all relevant to my performance problem, but they struck me as suspicious.
StarStriker, I’ve come across a very similar issue to you. I, too, build complex compound colliders with a single rigidbody. And I’ve also found in testing Unity 5 that it hates them.
Compound colliders coming into proximity with other colliders throws up tons of Contacts in the Physics profiler, though Physics.UpdateBodies stays pretty constant as a CPU time hog in the CPU profiler whether there are currently any contacts or not. Just having a complex compound collider (made up of many simple box colliders in my case) active in space along with other colliders in the scene seems to take a lot of CPU time, even if they’re nowhere near each other.
Changing the physics layer between colliding with itself or not makes no difference, which makes sense: Compound colliders can’t collide with other parts of themselves anyway, right?
You posted a while ago - have you found anything that improves the situation since your post or are you just dealing with it?
The contacts aren’t really a problem on their own. As StarStriker mentioned first and I noticed as well, it does seem a little strange that contact points appear in the profiler when the compound collider is near things, rather than only when it’s actually touching with them. But Physics.UpdateBodies performance stays pretty constant(ly bad) the whole time, whether there are any contacts reported or not.
It’s like PhysX takes a lot of processing just to move complex compound collider rigidbodies around.
OK, I’ve been doing a few tests, and it’s not just having a complex compound collider on a rigidbody that causes the performance hit. But I’m not sure what it is. I might not have the time to keep looking for much longer at the moment but I’m going to explore a little bit more.
One thing I’ve worked out, which might help someone, is that even inactive GameObject children on Rigidbodies introduce overhead in Physics.UpdateBodies. I guess it makes sense that even inactive GameObjects need their positions updated. But for performance that means you’d be better off moving inactive parts out temporarily.
Having said that, I’ve only been able to test the difference in the editor. Release build performance may be optimising that stuff out. Edit: The performance difference in release is still there but significantly smaller.
Hi all,
Facing the (exact!) same issue - sci-fi ships in space, relatively complicated physics inside because ships have components which are destructible.
On Unity4 it was performing smoothly, on Unity5 it is really struggling.
I have tried so many combinations of things, but before I was manually moving the ship around each frame with ship.transform.position = newPosition, in Unity5 that code is not workable due to performance.
Now I am setting the velocity on a rigidbody on the ship root gameobject and the game performs much better but still nowhere near the performance we were getting with Unity4 which is really disappointing.
Using velocities on ships rather than doing my own physics has other side-effects with my characters which would be great if I could just go back to the way I was doing it before but we need other features in Unity5.
It would be great if we could just move lots of colliders each frame to new positions and orientations but the physics system just can’t handle that it seems…
I am really hoping this is some sort of regression in the physics system that can be fixed but who knows?
Yeah, TH Interactive, what happens if you change all your ship.transform.position calls to ship.rigidbody.MovePosition (or the Unity 5 version since .rigidbody is deprecated)? Or even try just rigidbody.position as well as I think I recall from testing a while ago that it was faster performance-wise on rigidbodies than transform.position.
TH Interactive, maybe you could strip something down to show it? I don’t think there’s a bug in my case exactly, just some inefficiency that I need to work around. I think the space game people are having a worse time than me.
To answer Nition’s earlier question a bit, I don’t recall ever really finding a resolution on my end; one thing I altered that seemed to improve things a bit was to avoid having large, oddly oriented collision objects in the environment because (I presume) their AABB bounds were covering a large area that made collision culling harder. That’s just resolving the symptoms rather than the root cause, though, and relatively expensive physics calculations are still a concern for me.
Nition, did you get anywhere with figuring out where the trigger for the problem is, if just having compound colliders isn’t enough? When I’ve got a spare moment I’ll try and look into my own stuff to see if there’s something I can turn off that fixes it and try to narrow this down.
How are you moving your rigidbodies around? Make sure you’re not using transform.position on them anywhere (at least, certainly not every frame). And if you are, compare the performance of doing that vs. using rigidbody.position, and vs. using rigidbody.MovePosition().
I basically found that yes, my physics performance in Unity 5 kind of sucks, but in my case it sucks just about as bad in Unity 4 as well, so I have less of a specific issue with Unity 5 here.
I had one case of using transform.position (on the camera following my vehicles) but changing that to use Rigidbody.MovePosition didn’t have an effect on the cost. What did have an effect was removing the rigidbody entirely and managing the movement entirely manually; given the use case, it didn’t make sense to have a rigidbody there at all, and I suspect it’s only there for legacy reasons.
One the vehicles themselves, I have a line of code that uses Rigidbody.MovePosition/MoveRotation to move the object with the rendered meshes in sync with the collision object, which I may be able to pull the same trick on (I’ve recently changed them so that the renderable portion has no physics whatsoever), but I’m a little mystified as to the root cause. Best guess is that MovePosition incurs a substantial performance penalty when the moved object has a large transform hierarchy under it. If I delete the objects in that hierarchy the UpdateBodies cost in the profiler drops to pretty much nothing.
Not sure if removing the MovePosition calls and moving hierarchies around without rigidbodies actually helps with the performance, though. It’s entirely conceivable that the same cost is incurred that way and it’s just hidden somewhere else in the profiler, and the overall footprint is small enough it’d be tough to detect in the noise noise. I also don’t really know why this wasn’t an issue for me in Unity 4, or why the cost is so high relative to the size of the hierarchy.
If I have time this weekend I’ll look into building a test project that can actually reproduce this reliably.
I did a similar test - some of the stuff under my Rigidbody needed to be moved because it has visual stuff on it, but it didn’t have colliders, so I tried moving it out of the heirarchy. I added a script that just took the transform position of the rigidbody base and synced it with the transform positition of the separate object heirarchy’s base - keeping the visual stuff moving but not part of the compound rigidbody.
Sure enough, physics performance improved but, the saved time was lost again about equally with the transform sync script - which showed up in the profiler as the script itself. So it’s quite possible that there are no real savings to be made that way.
Sounds like it’s updating the underlying transform hierarchy that’s eating up all those cycles in the profiler. Maybe I didn’t lose any physics performance, the cost just got shifted to Physics.UpdateBodies instead of the script calling MovePosition like it used to. If I understand it correctly Unity updates transform hierarchies fairly proactively; if you move an object twice in a frame, all the children get updated twice as well so that any calculations you do on the children remain accurate.
If that’s the case then maybe the best approach is to take a cue from the animation system and hide/internalize the transforms so those updates don’t need to happen at all. Do the rendering manually through Graphics.DrawMesh and precalculated offsets.
I’m leery of taking that approach in my case just yet; at least, not for the vehicles themselves. That’s a big, complicated premature optimization for a relatively tiny gain, and I’ve already cut my UpdateBodies cost down by trimming out a lot of unnecessary child transforms. I think I’ll be reorganizing my camera/cockpit code to not follow the ship around the scene, though, and instead to just be rendered on a separate camera so that it can stay static while appearing to maintain pace with the ship. Added bonus is that it’ll help resolve some of my floating point issues as well…
One other thing I’ve noticed is that even inactive GameObjects get updated all the time as their parents move (which makes sense when you think about it since you can query the position of an inactive GO, but it’s maybe a bit counter-intuitive), and they accrue the same overhead.
You can combine separately moving meshes into a single SkinnedMeshRenderer, but that still requires moving the original transforms since you’re now using them as the bones. You could theoretically do that directly in a shader instead by passing in the matrices (which I seem to recall might be somewhat difficult in Unity? This is getting beyond my expertise) and avoid actually moving any transforms around. For non-moving stuff (well, stuff that moves with the rigidbody but doesn’t move any more than that) you can combine that all into one big mesh pretty easily.
Of course that’s avoiding our main performance concern which is all the actual colliders.