Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Physics performance problem with complex colliders

Discussion in 'Physics' started by starstriker1, Jun 8, 2015.

  1. starstriker1

    starstriker1

    Joined:
    Jul 15, 2012
    Posts:
    38
    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?
     
  2. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,618
    are colliders coliding with each other causing the contacts perhaps... are your physics layers set up so this doesnt happen?
     
  3. starstriker1

    starstriker1

    Joined:
    Jul 15, 2012
    Posts:
    38
    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.
     
  4. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    741
    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?
     
    Last edited: Nov 25, 2015
  5. Roni92pl

    Roni92pl

    Joined:
    Jun 2, 2015
    Posts:
    268
    Sounds strange. But remember that if your rigidbody reports contact points, you can debug their positions to investigate, what is actually happening.
     
  6. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    741
    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.
     
  7. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    25,577
    Bug reports are welcome as always. I haven't seen this myself.
     
  8. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    741
    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.
     
  9. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    741
    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.
     
    Last edited: Nov 27, 2015
  10. TH-Interactive

    TH-Interactive

    Joined:
    May 26, 2013
    Posts:
    34
    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?
     
  11. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    25,577
    not using rigidbody.MovePosition ?
     
  12. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    741
    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.
     
  13. MortenSkaaning

    MortenSkaaning

    Joined:
    Jan 16, 2015
    Posts:
    120
    Hi,

    Can I get one of you guys to submit a bug with a reproduction scene in? It's hard to deal with otherwise.

    Regards,
    Morten
     
  14. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    741
    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.
     
  15. starstriker1

    starstriker1

    Joined:
    Jul 15, 2012
    Posts:
    38
    ...are we all building the same damn game? :p

    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.
     
  16. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    741
    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.
     
  17. starstriker1

    starstriker1

    Joined:
    Jul 15, 2012
    Posts:
    38
    Alright, found some time to dig into it a bit.

    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.
     
  18. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    741
    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.
     
  19. starstriker1

    starstriker1

    Joined:
    Jul 15, 2012
    Posts:
    38
    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...
     
  20. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    741
    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.
     
  21. starstriker1

    starstriker1

    Joined:
    Jul 15, 2012
    Posts:
    38
    I'm beginning to think the colliders AREN'T the main performance concern here; actual physics solver presence on the profiler is almost nil, at least for me (nice thing about flying around in space is that running into things is a rare occurance). Just by killing a few dozen transforms on my vehicles that didn't need to be there I was able to save almost half a second on my frame time.

    I remember that article (that's me in the comments). I don't think retaining the bone transforms is that big a deal so long as you're not going too crazy with them. That said, writing your own GPU skinning solution is entirely doable; push an array of transformation matrices into the shader (there is poorly documented but entirely functional array support), then index into it in the vertex shader. Offhand I don't know a way of accessing the boneweights or bone indices in the shader and a quick search didn't find anything, but there's nothing stopping you from approximating that data by shoving it into one channel of an unused UV set or the vertex colours.

    I use the latter approach in a combined mesh setup of my own, with the R vertex colour channel corresponding to the ID of the original mesh in the combined mesh. Since each vertex then can index into an array of float4s, I can then modify material properties to colour individual submeshes and create a damage display.

     
  22. MortenSkaaning

    MortenSkaaning

    Joined:
    Jan 16, 2015
    Posts:
    120
    can you guys estimate how much time the Physics.UpdateBodies are taking in your frame? We know we can improve the performance of that code, but it's difficult to prioritize until we know what impact it has in people's games.

    Until we do that, the best perf gains are had by having as shallow object hierarchies as possible and setting non-moving Rigidbodies as kinematic.
     
  23. Roni92pl

    Roni92pl

    Joined:
    Jun 2, 2015
    Posts:
    268
    Thats very interesting topic you mentioned. I never thought about that, but under which group such calculations are included(in profiler)? ( I mean child-parent relative positions and rotations calculations - not physx related, just transforms positions).
    Also does that mean that rigidbody with five box colliders that are under root rigidbody GO will be faster than the same setup, but with every collider being child of another?
     
    Last edited: Dec 14, 2015
  24. MortenSkaaning

    MortenSkaaning

    Joined:
    Jan 16, 2015
    Posts:
    120
    it's all that Physics.UpdateBodies spends time on.

    The only thing that matters are the number of Rigidbodies and how many transform parents they have.
     
  25. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    25,577
    We have 30 ragdolls using partel lang's puppet master (author of final ik) and performance is tanking quite a bit. Any chance of optimising scenarios like that? pretty please :)
     
    Dantus likes this.
  26. starstriker1

    starstriker1

    Joined:
    Jul 15, 2012
    Posts:
    38
    In my case I was getting around .8ms of Physics.UpdateBodies in a typical scenario when I started, which is a fairly big cost when I'm aiming for a VR capable framerate. I've since been able to drop that to .2-.3 ms in the same scenario by trimming down my transform hierarchies and making my (fairly complicated) camera object not use a rigidbody. The latter saved about .2-.3 ms on its own, but I haven't been able to benchmark it yet to see if that results in an overall savings or if that cost has just been moved elsewhere in the project, which I suspect may be the case
     
  27. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    741

    I think you mean transform children? So just to confirm, if you have a Rigidbody with 50 children, having them all as direct children of the rigidbody vs. having every one as a child of the previous one (so a deep instead of a broad heirarchy), performance would be the same?

    I was thinking the same as Roni92pl - in your first comment it sounded like you might have meant "flattening" the heirarchy could be a performance gain.
     
  28. starstriker1

    starstriker1

    Joined:
    Jul 15, 2012
    Posts:
    38
    I'd be surprised if that was the case; my substantial performance gain came from removing a relatively flat child hierarchy from the base object (one "folder" object at the root, with something like 40 children). It would seem like the leaf nodes matter.
     
  29. MortenSkaaning

    MortenSkaaning

    Joined:
    Jan 16, 2015
    Posts:
    120
    I'll increase priority on this in our backlog.
     
  30. Scarzzurs

    Scarzzurs

    Joined:
    Oct 6, 2014
    Posts:
    13
    Any news on this? I suspect we may have run into the same bottleneck.

    Starstriker1 is talking about a rigidbody with 40 descendants, but in our game up to 30-40 enemies may move about at the same time. Turns out EACH of these have around 250 descendants, where around 170 are active. Doing the math this means 7500 to 10000 updates each physics physics frame updating only the hierarchies of our enemies. I guess this could explain the 30% Physics.UpdateBodies I've seen in the profiler severely crippling the CPU on some machines?

    So far I've halfed the number of physics frames per second, but it seems simplifying the enemies structure could be worthwhile as well. Unfortunately many of the objects are necessary for anchoring and animating the enemies that also contain ragdolls and gib parts. Perhaps the technique of "parking" some of these (deactivated) objects outside the hierarchy could help somewhat but must also be weighed against time to implement, increased complexity and slower workflow. Some kind of Unity provided optimization would be greatly appreciated!
     
  31. MortenSkaaning

    MortenSkaaning

    Joined:
    Jan 16, 2015
    Posts:
    120
    I did a proof of concept, but we've been busy fixing stuff since.
    Can you give me a project with those hierarchy characteristics? I'd like some real world scenarios to optimize on.
     
    Scarzzurs likes this.
  32. Scarzzurs

    Scarzzurs

    Joined:
    Oct 6, 2014
    Posts:
    13
    Thanks for the quick reply MortenSkanning. It's nice to hear you've been working on it!

    Our project is rather large, cannot be easily split into smaller chunks and I'm uncertain as to whether I'm allowed to disclose the complete source code for our game. So at the moment I cannot provide with anything that you can test on. I will let you know if anything changes in this regard...
     
  33. Scarzzurs

    Scarzzurs

    Joined:
    Oct 6, 2014
    Posts:
    13
    Oops, I realise I've made a slight miscalculation! I forgot that each enemy and their weapons/items features extensive use of object pooling that stores deactivated objects (AudioSources, ParticleSystems, projectiles and so on) in their hierarchy when they are no longer used until needed again. This means that the numbers that I presented previously is before enemies move, see the players, attack, take damage, becomes ragdoll and so on. The longer they live and the more they do, the more extensive their hierarchy (of deactivated object) become. A quick test showed about 30% increase in deactivated children for rather simple enemies after a few seconds of combat.

    Just to elaborate: By placing such deactivated pooled objects in the same hierarchy after use, we avoid having to manually clean them up upon object pool destruction (i.e. enemy death). So parking them elsewhere is not an straightforward option. We are using object pooling in the first place to avoid the costly and redundant re-instantiation (and destruction) of objects, thus removing object pooling would in turn lead to performance loss.

    I'll grant that the new 30% increased object count may not be entirely important for our specific game, but I guess it is worth noting that object pooling could be a common use case that could pose much further performance impacts for other Unity users...
     
  34. MortenSkaaning

    MortenSkaaning

    Joined:
    Jan 16, 2015
    Posts:
    120
    I don't need your whole project :) I just need a script that creates and move Rigidbodies in the same patterns as your game.
     
  35. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    545
    I'd love to see movement on this. My project is getting hit with 8ms of Physics.UpdateBodies. Airships with a bunch of "Trigger" hitboxes parented to the main rigidbody..
     
  36. hoesterey

    hoesterey

    Joined:
    Mar 19, 2010
    Posts:
    545
    Do you still need a project? I can do the work to give you one but I think you could just create an object with a deep hierarchy of 1-2 hundred children to test this, its pretty easy to reproduce.

    Just adding 20-50 game objects per ship, with no colliders and just a mesh renderer that turn on when a ship is damaged had a major impact on physics performance. Odd being that they are not rigidbodies and don't have colliders. Perhaps the physics engine is doing something odd and checking every child to see if it has a collider or rigidbodies on every update?

    Any optimizations here would help, my design is severely limited due to the performance hit of Physics.UpdateBodies. It reaches unacceptable ms levels with only 9 or so ships moving in the scene. And each ship only has 1 cylindrical collider that effects its 1 rigidbody. All other colliders on the ship are triggers used as hitboxes.
     
  37. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    741
    You're always better off in terms of getting the thing actually fixed if you can make a test project and send it in as a bug report. I know it's a hassle but that's what will stop someone at Unity taking the time as well. You can post the bug number back in the thread.