Search Unity

Moving static collider vs. Kinematic Rigidbody: dubious official documentation and performance cost

Discussion in 'Scripting' started by fermas, Oct 7, 2015.

  1. fermas

    fermas

    Joined:
    Sep 21, 2015
    Posts:
    15
    Hi all. What I really want to know is the following: in Unity 5, is it less expensive to have moving static colliders or moving Kinematic Rigidbodies?

    However, the documentation on that is somewhat dubious.

    When the new features of Unity 5 was being announced, it was claimed that it would bring the following gift: "Moving Static Colliders will be a lot less expensive" (see http://blogs.unity3d.com/2014/07/08/high-performance-physics-in-unity-5/).

    Later, when it was released, we were told something even happier: "moving static colliders does not cause performance penalty anymore" (see http://unity3d.com/unity/whats-new/unity-5.0).

    However, these two claims are not the same. One makes the reader think that the penalty would be diminished. The other makes the reader think that the penalty is all gone. That's an important difference because having a moving static collider could have become much less expensive but be still worse than having a moving kinematic rigidbody.

    So, which is true? If the penalty is all gone, then the answer to my main question is simple: in case one does not need any of Rigidbody goodies, then having a moving static collider is better since it is as simple as one can gets. If the penalty was diminished but not gone, then things are more complicated and I would love to hear more about that.

    Thanks a lot for your time.
     
    Last edited: Oct 7, 2015
    Plains likes this.
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    so, this is more a PhysX 3.3 question than anything.

    A static collider implements the PxRigidStatic type:
    http://docs.nvidia.com/gameworks/co...sx/apireference/files/classPxRigidStatic.html

    A collider with a Rigidbody uses the PxRigidDynamic type:
    http://docs.nvidia.com/gameworks/co...x/apireference/files/classPxRigidDynamic.html

    Setting a PxRigidDynamic kinematic via the PxRigidBody::setRigidbodyFlag(...) method, when that is done you can move it like a kinematic object via the PxRigidDynamic::setKinematicTarget(...) method. Where as static bodies are moved via PxRigidActor::setGlobalPose(...). We can read about this here:
    http://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/guide/Manual/RigidDynamics.html

    I bolded a caveat that should be of interest to us.

    So moving a static body still acts differently than a kinematic rigidbody, because you're just setting its global position. Where as a kinematic body will move the object as if its a object that can't be effected with force, but will push other objects out of the way (basic collision overlap, and adjust, no force application).

    Unity says this on their blog entry you linked:

    So basically the bounding box tree (its a data structure of all bounding boxes for fast overlap testing... if bounding box doesn't overlap, they don't overlap, so no point in testing any detailed collision testing) needs to be recalculated when something is moved. And in PhysX 3 the dynamic and static colliders now exist in the same tree. So the rebuild costs the same either way.

    I'm going to assume this means that in PhysX 2, because of the "memory" comment, it was a more simple structure as it assumed it would never change. I'm betting it didn't save the neighbouring nodes in the tree, which would save memory. As a result though, moving a static collider meant you have to rebuild a tree. Where as if you had neighbouring node information, you could just find its location in the tree and update the the neighbour nodes if and only if they have to.

    Which is how the dynamic objects would have been treated. These will move, so updating the whole tree would be insane, so it only updates the localized information relative to a specific node and its neighbour nodes.

    If in PhysX 3 they're all in the same tree, updating these positions for either static or dynamic objects is exactly the same. Hence the HUGE efficiency increase for moving static objects.

    BUT, we still have the difference in cost relative to the different translation methods for each. Dynamic using the 'setKinematicTarget' method, and the static using the more generic 'setGlobalPose' method.

    These methods will obviously do different tasks, so will operate at different speeds. But I don't know of any information out there that would compare the two directly. But the difference is probably negligible... and may even lean in the favor of 'setGlobalPose' as its a more generic movement method. Since it teleports, it doesn't have to calculate the overlaps that may occur by its movement, which potentially makes it faster.

    BUT, this does mean that if an overlap does result, the next tick of physics will come with the potential of a collider existing inside this moved static collider. And it must quickly eject itself from that collider. This means the cost is back, and I have no idea what that cost might be. But I bet it again is comparable to moving out of the way in the 'setKinematicTarget' again making them almost the same... but with the added bonus of occurring in post, meaning the test only occurs if and only if the overlap actually did occur.

    BUT AGAIN, this means that simulation can become unpredictable. It doesn't know where the static collider came from, so it doesn't have that information to calculate in which direction to adjust itself to no longer overlap. So it'll probably just take the shortest path. Furthermore it might just get fully consumed and stuck inside the static collider.



    TL;DR

    I bet they're almost the same in cost. With moving static colliders potentially faster in the case of moving through open space. But more equal in the case where collisions would result, but with kinematic Rigidbodies having more predictable adjustments of the colliders it hits.

    I'd use moving statics if we're adjusting world geometry as a whole (thinking infinite runner where the entire worlds geom scrolls).

    Where as I'd use moving kinematic rigidbodies when its something moving within a simulated area (think a moving platform that might collide with debris that should get pushed out of its way). Noting this means calling the 'Rigidbody.MovePosition' method. Setting the position via transform would just result in a call to 'setGlobalPose' for the collider, which is exactly the same thing that occurs when moving a static collider.



    With all that said, I could be completely wrong.

    I'm basing this off a cursory read of the PhysX 3.3 documentation.

    In the end, PhysX still distinguishes between static objects and dynamic objects, and they probably have good reason for that. I'd use static for static, and dynamic for dynamic.

    We just get the benefit that if that static collider must move, it's not so expensive, like in the case of an infinite runner. You could put all gameobjects in some parent GameObject and just scroll that across the screen with little performance hit, and all objects inside will simulate appropriately.
     
    Last edited: Oct 7, 2015
  3. Fissll

    Fissll

    Joined:
    Jan 30, 2015
    Posts:
    70
    @lordofduct this was really helpful ... but is it the same for triggers?
     
    sanmn19 likes this.
  4. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    As always some tests would quickly clear it up.
     
  5. Fissll

    Fissll

    Joined:
    Jan 30, 2015
    Posts:
    70
    yeah I'm fairly new to optimizing stuff and also ... does it matter if the rigidbodies are kinematic when they are triggers?