Search Unity

What exactly is considered "moving static colliders"?

Discussion in 'Scripting' started by ronronmx, Nov 21, 2012.

  1. ronronmx

    ronronmx

    Joined:
    Aug 16, 2010
    Posts:
    201
    I have read and heard ( from UNITE videos ) many times that moving static colliders is a big no-no, so if you're gonna move something that has a collider then you should always add a rigidbody.

    But I'm confused as to what is considered "moving" a static collider? For example, in my scene I have some object which all have a MeshCollider, but no rigidbody. Each of them has a script attached which changes their position when something happens, like so:

    Code (csharp):
    1.  
    2. public Transform target;
    3. Vector3 oldPosition, newPosition;
    4.  
    5. void Start()
    6. {
    7.     oldPosition = transform.position;
    8.     newPosition = target.position;
    9. }
    10.  
    11. void Update()
    12. {
    13.     // Here I move my object to a new position in 1 frame. This object has a MeshCollider attached.
    14.     // Is this considered moving a static collider and should I attach a rigidbody to this object?
    15.     if( timeToMove == true )
    16.     {
    17.         transform.position = newPosition;
    18.     }
    19.     else
    20.     {
    21.         transform.position = oldPosition;
    22.     }
    23. }
    24.  
    Thanks for your time guys!
    Stephane
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Moving a collider that doesn't have a rigidbody is moving a static collider.

    --Eric
     
    LuckyMisterSleven likes this.
  3. ronronmx

    ronronmx

    Joined:
    Aug 16, 2010
    Posts:
    201
    What about if you have a GameObject with children, setup like this:

    - Parent (Collider Rigidbody)
    -- Child1 (Collider)
    -- Child2 (Collider)
    etc...

    and you're moving the Parent, should each child which has a Collider also have a Rigidbody, or are they fine without since you're not moving them directly, they're just changing global position because of the Parent being moved, but their local position remains the same? Also, is enabling/disabling static colliders also considered "moving" them?

    Thanks Eric!
     
  4. w00dn

    w00dn

    Joined:
    Apr 28, 2010
    Posts:
    275
    AFAIK, that setup acts as a compound collider (several colliders acting as one through parenting). as long as the parent has a rigidbody, you're fine.
     
    Harinezumi and dreamer- like this.
  5. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Correct; you should not use a rigidbody for children if the parent has a rigidbody.

    --Eric
     
  6. ronronmx

    ronronmx

    Joined:
    Aug 16, 2010
    Posts:
    201
    Got it, thanks guys!
    One last question if you don't mind? What if I move one of the children directly - parent remains still, children moves - then does that child need a Rigidbody or is this still acting as a compound collider?

    Thanks again :)
     
  7. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    interesting...

    adds rigidbodies back to projectiles.
     
  8. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Yeah, it's actually in the unity docs regarding using a rigidbody for speed in these cases. I'm not going to lecture anyone, just pointing out this could be clarified in the docs more, perhaps.
     
  9. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    Just had a read through the docs for rigidbody component and couldnt see anything that specifically stated if its moving, put a rigidbody on it, but this hardly surprises me.

    I find unity docs lacking at best
     
    Harinezumi and AaronC like this.
  10. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    http://docs.unity3d.com/Documentation/ScriptReference/Collider.html

    Rigidbodies are for physics (eg: moving things), I think it was safe for the author to assume you knew that when you got there.
     
  11. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    It could use clarification though. Saying recommended isn't really clear. It's also mentioned in a similar manner elsewhere in the docs, and equally as vague. The docs need to be a bit more verbose given so many people are asking the same question. Not all of them are dumb enough to not read docs.
     
  12. Deleted User

    Deleted User

    Guest

    It's also important to use the rigidbody MovePosition and MoveRotation functions instead of directly changing the transform - last time I checked, changing the transform of a kinematic rigidbody was actually a lot slower than moving it as a static collider.
     
  13. Stephan-B

    Stephan-B

    Joined:
    Feb 23, 2011
    Posts:
    2,269
    To illustrate or help quantify this point, here are the results of a test I did a while ago. The performance difference is significant.


     
  14. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    It annoys me that I'm going to have to build performance scenes just to verify what costs the most. Its something ive been thinking about doing for a while though.


    Cant say I ever looked at the collider docs.. it would make much more sense to put statements like that into the rigidbody component...

    More definitive statements like this would be great...
    "If you are moving a collider, you must put a rigidbody on it to reduce physics calculations" or something along those lines so its blatantly obvious that if you dont do it, youre taking a performance hit.

    The funny part was during my 'performance optimisations' I removed all the rigidbodies from my projectiles and put in some object pooling. Everything seemed alot faster, but i guess it was probably more the pooling than anything.
     
  15. ronronmx

    ronronmx

    Joined:
    Aug 16, 2010
    Posts:
    201
    Wow...what a huge difference! It would be nice if the docs mentioned this as well, I had no idea it was THAT much slower! What about the difference between moving a static collider and a rigidbody through transform.position instead of rigidbody.MovePosition or rigidbody.position?

    I hear you...I think that things like these which take a big performance impact should really be talked about in-depth in the docs.

    BTW guys, is enabling/disabling a static collider considered "moving" it, since the collider isn't part of the scene anymore?
     
  16. ronronmx

    ronronmx

    Joined:
    Aug 16, 2010
    Posts:
    201
    So I just did my own tests...

    The code for the test iterates 500000 times in Start and moves the object to Vector3(0,0,0) each iteration.

    Object with NO Collider and NO rigidbody:
    transform.position: 2.540ms

    Object with Collider and NO rigidbody:
    transform.position: 11.296ms

    Object with Collider and Rigidbody:
    transform.position: 20.429ms
    rigidbody.position: 1.689ms
    rigidbody.MovePosition(): 1.701ms

    So, if you're gonna move/rotate/change an object which has a collider, add a rigidbody and move/rotate the object via its rigidbody. And as you can see above, if you're moving the object via its transform, IT'S FASTER TO MOVE A STATIC COLLIDER THEN A COLLIDER/RIGIDBODY SETUP! So unless you're going to changes all your movement to use rigidbody instead of transform, do not add a rigidbody as it is slower. But if you care about performance, then add that rigidbody and change all your movement code to rigidbody.position instead of transform.position.

    Then again, the test above is over 500000 iterations, so none of this matters much if you're only doing it once a frame...
     
    JabuGames, alexzzzz and Mindaugasw like this.
  17. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    Interesting stuff.

    You should extend your tests a bit...

    try doing transform.move with a kinematic rigidbody/collider... be interested to see those results.
     
  18. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    which is fine if you have 1 object, now multiply that by 1000/objects and it definitely matters.
     
  19. ronronmx

    ronronmx

    Joined:
    Aug 16, 2010
    Posts:
    201
    In my test above, the rigidbody is kinematic on the collider/rigidbody setup. I haven't tried testing with a non-kinematic rigidbody since it is not the issue. Unless I understood you wrong? And yes, the results are interesting!

    Very true, very true!
     
  20. Loius

    Loius

    Joined:
    Aug 16, 2012
    Posts:
    546
    Man, now I've got to rewrite my movement scripts. At least it's reasonably simple to switch from tx.position to rb.position. Thanks!
     
  21. w00dn

    w00dn

    Joined:
    Apr 28, 2010
    Posts:
    275
    I wonder how much that depends on how big the physx data structure is that has to be rebuilt upon moving a static collider. i.e. in a real world setup, you might have a couple hundred colliders, not just three or four like in a test scenario.
     
    forestrf likes this.
  22. ronronmx

    ronronmx

    Joined:
    Aug 16, 2010
    Posts:
    201
    Yes, except you have to make sure that the object you're moving has a rigidbody attached.

    What I do now on all my movement scripts (in Start or Awake) is check if the gameObject (the parent) - or any of its children - has a collider attached. If it finds a collider on the object itself or any of the children, I then check if the object (the parent) has a rigidbody already attached, and if it doesn't have one, I add one. Now if the above is true, I then move the object via its rigidbody.position property (since I know it will have a rigidbody for sure now). But if I can't find ANY colliders on the object or any of its children, I then use the transform.position property to move it.

    I also did some more testing by disabling all colliders found on a object prior to moving it, and then re-enabling them after the move. Doing this is just as fast as moving a object with no colliders attached, and MUCH faster then moving "static colliders" even though you have to go through all the colliders found and disable/enable them every frame. So if for some reason you can have rigidbodies on all the objects you are moving, you can use this method of disabling colliders/move object/re-enable colliders. It's still slower then moving using rigidbody.position (about 5-6 times slower), but it will be a lot faster then moving static colliders (about 275 times faster). If I'm wrong about this please correct me, all I know is the speed tests I did came up with these numbers, but it's possible my tests weren't done correctly.
     
  23. ronronmx

    ronronmx

    Joined:
    Aug 16, 2010
    Posts:
    201
    Also note that my statement is only true when using transform.position for both case. If using rigidbody.position with the Collider/Rigidbody setup, then that's much much faster then moving a static collider.

    And yes i wonder the same thing...I actually wonder a lot when it comes to physics as the docs don't go into details, and there is a lot of unknown here, at least for me.
     
  24. dreasgrech

    dreasgrech

    Joined:
    Feb 9, 2013
    Posts:
    205
    One problem I've noticed with MovePosition/rigidbody.position is when having a nested-rigidbodies setup.

    -> Root Rigidbody Moving Platform
    ---> Child Rigidbody Character

    With this setup, the character moves independently on the platform but is also moved when the platform is moved.

    What I've noticed is that if I move the moving platform with "transform.position", the child rigidbody character correctly moves with it but if I move the moving platform with MovePosition/rigidbody.position, the child rigidbody character does not move with it.

    What is the reason for this?
     
  25. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    You should never have a rigidbody on a child.
     
  26. dreasgrech

    dreasgrech

    Joined:
    Feb 9, 2013
    Posts:
    205
    The reason I have to parent my rigidbody character to another rigidbody (the platform) is because it's a moving platform and I need the character to be able to be "moved" with this platform, so I parent the character to it when the character gets on it and unparent it when the character gets off it.
     
  27. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    Yep, I understand the reason for the setup. I've never tried moving a rigidbody platform, so not sure what the best solution is.

    Im assuming the parenting thing is still a no-no... maybe that's actually changed.

    using Transform.Position to a move a rigidbody/Collider setup is definitely still the wrong way to do it (unless its kinematic, then its ok). The best way I can describe it, is adjusting Transform.Position is like dragging it around in the scene using the editor.. all the children move with the object selected.
     
  28. dreasgrech

    dreasgrech

    Joined:
    Feb 9, 2013
    Posts:
    205
    The problem though is that even when it's kinematic, the performance hit of moving a compound rigidbody (with a couple of child colliders) with transform.position is huge.

    On the other hand, moving it with rigidbody.MovePosition is very cheap...but when using rigidbody.MovePosition, my child rigidbody character is not "moved" along with the platform.
     
  29. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    Well if youre moving the kinematic rb, and have children with non-kinematic rb's, the same performance hit will occur.

    I would probably simulate parenting and use MovePosition on the player.
    1. Player lands on platform, holds reference.
    2. FixedUpdate, move player by amount the platform moves
    3. If player jumps, remove reference.

    It sounds clunky, and im not sure how reliable it would be.. It seems to be a common problem with Unity/Physics though. Might have to experiment with moving platforms myself.
     
    Harinezumi likes this.
  30. geroppo

    geroppo

    Joined:
    Dec 24, 2012
    Posts:
    140
    Hey guys and i was wondering, if you have a parent with NO collider or rigidbody attached that is moving using transform.position, this parent has childs WITH colliders attached, what should i do in that case ? im confused x.x
     
  31. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    That's a compound collider. Add a Rigidbody to the parent (I believe) and treat it like any other Rigidbody with a compound collider.
     
  32. TylerPerry

    TylerPerry

    Joined:
    May 29, 2011
    Posts:
    5,577
    I think that depends on the behaviour you're looking for.
     
  33. Deleted User

    Deleted User

    Guest

    Attach a kinematic rigidbody to the parent and move with the Rigidbody Move function instead of altering the transform.
     
  34. geroppo

    geroppo

    Joined:
    Dec 24, 2012
    Posts:
    140
    Thanks, what im doing is basically move a bunch of objects that can be collided with, and all those objects move at the same speed (and same behaviour ), so i thought it would be better to move the parent with 1 script than to move 10 individual objects in the same way with 10 scripts.
     
    Last edited: Jun 30, 2014
  35. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    781
    I don't think anyone ever answered ronronmx's final question, which I'm not sure about either:

    i.e. What's the deal with moving transforms that have colliders, that are children of a Rigidbody, in a compound collider? Like for instance you might have a tank compound collider rigidbody with a couple of the colliders on a turret that rotates.
     
    Last edited: Nov 11, 2014
  36. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    well, his original question was answered (based on title).

    You raise an interesting side question. The point really is that the tank has a rigidbody attached to it, so its fine to move those parts/colliders. Sure using Translate/Rotate is generally not the correct way to move a rigidbody, but for moving children there is no alternative.
     
  37. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Yeah, from memory you're not meant to have a Rigidbody that's a child of another Rigidbody. I think if you move a child collider in a compound Rigidbody you need to invalidate the state of that collider, which I understand to be the expensive part of doing this the "wrong way" where the collider you're moving is a part of the static set.

    So, while I have done no testing to verify this, an educated guess suggests that in this particular case moving the child transforms directly is in fact the right way. The physics system needs to get told that they've moved at some point, and it already knows that they're a part of a Rigidbody rather than a part of the static world, so surely it would behave accordingly and leave the static set alone...
     
    Harinezumi likes this.
  38. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    781
    Might be interesting to test a "tank with turret" setup with a couple of options:

    Option 1:
    - Tank base with rigidbody and base collider, then a child GameObject for the turret with another collider. So it's a rigidbody compound collider.
    - Rotate the turret GO around with transform.rotation

    Option 2:
    - Tank base with rigidbody and base collider, then a fixed joint, then a child GameObject for the turret with another rigidbody and collider (I think child RBs are OK as long as they're connected with a joint?)
    - Rotate the turret GO around with rigidbody.rotation

    And yeah, I know the answer to this is "why don't you test it yourself?" Just a bit busy at the moment. Also I'm sure there's like an Option 3 somewhere.

    Actually, you can even do rotation-limited Configurable Joints.
     
    Last edited: Nov 13, 2014
    Harinezumi likes this.
  39. georgeq

    georgeq

    Joined:
    Mar 5, 2014
    Posts:
    662
    Apparently this does not affect the 2D system, or at least not in Unity 5. I made a simple animation with 14 moving objects each with its own BoxCollider2D, then I built the Android player and installed it on a low end smatphone, and checked how it behaved on the Profiler... The frame rate behaves very stable at 60FPS with or without a RigidBody2D attached to the parent GameObject, there's no noticeable difference between the two versions. I also tested adding a RigidBody2D to all the child GameObjects but without a RigidBody2D attached to the parent object, the fame rate is still around 60FPS on average, but with spikes that slow down the frame rate near to 15FPS.

    Another test consisted in duplicating the parent object 64 times and then play the game in the editor, this time the frame rate dropped below 15FPS, both with and without RigidBody2D attached to the parent objects. Again, no noticeable difference could be observed.

    So it seems that having or not having a RigidBody2D simply makes no difference, or at least the difference is so tiny that can be safely ignored.
     
  40. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You should really be measuring stuff in ms, not fps. Frames per second is affected by too many things that have nothing to do with what you're measuring. e.g., vsync...if one method takes 10ms to do and a different method takes 5ms, then the first method is twice as slow, but you'd still be getting 60fps, assuming vsync with a 60Hz display. Or you could have one method take 16ms, getting you 60fps, and another method take 17ms, which would drop to 30fps even though there's not a huge difference.

    --Eric
     
    hippocoder and Kiwasi like this.
  41. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    This was supposed to be no longer a problem from 5.0 onwards. I've never benchmarked it to be sure, but it's a good reminder to check before relying on a thread from three years ago.

    Three years is a long time in terms of engine development.
     
  42. Antony-Blackett

    Antony-Blackett

    Joined:
    Feb 15, 2011
    Posts:
    1,778
    They said they were going to fix this in Unity 5... I believe they may have, but can someone confirm my suspicion that creating a new static collider, or setting a gameobject with a static collider on it to inactive and active again is still slow?
     
  43. neonblitzer

    neonblitzer

    Joined:
    Aug 5, 2013
    Posts:
    13
    According to lordofduct here, static and dynamic objects now share the data structure in PhysX which could imply that moving either would cost about the same. Moving kinematic rigidbodies could still be more robust in case of collisions.
     
  44. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    haha, so funny reading my posts from a way back.

    suchnoob
     
    GarthSmith and hippocoder like this.
  45. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Same but... I also google for problems and find I've answered myself from the past. A lot.
     
  46. chriscode

    chriscode

    Joined:
    Mar 2, 2015
    Posts:
    49
    If one put colliders in a NoCollisions type layer would this alleviate the cost of movement? I think this is quite a common thing: detailed colliders for raytracing, but more basic shapes for collisions with other objects....
     
  47. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    I would guess that the answer is "no", because I wouldn't assume that the physics system is aware enough of how layers are used to do that. Guesses are useless, though - if it matters, test it.

    (As an aside, though, if you're going to ray trace against it the collision data still has to be maintained, so I'm not sure how it'd be different.)
     
  48. Mindaugasw

    Mindaugasw

    Joined:
    Oct 25, 2014
    Posts:
    13
    I'm thinking how to optimize my own game so I did some testing.
    All times are in ms, all test were done with 2D physics.

    Moving object 500 times through 500 frames (once each frame)


    Moving 500000 times through 500 frames (100 times each frame)


    • Moving object with RigidBody is faster than using Transform
    • Setting Transfrom.position is faster than using Transform.Translate
    • Using RigibBody.MovePosition() seems to be the fastest way to move objects.
     
    khaled24, LucasVHO and Harinezumi like this.
  49. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Any chance you could show us how you made the measurements? It seems odd to me that anything is faster than setting a transform's position, since all of the other approaches ultimately have to do that as well.
     
  50. Mindaugasw

    Mindaugasw

    Joined:
    Oct 25, 2014
    Posts:
    13
    I used Stopwatch class from System.Diagnostics to measure time.
    Full code if you're interested:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Diagnostics;
    4.  
    5. public class TestScript : MonoBehaviour {
    6.  
    7.     public Transform TTT; // Thing To Transform
    8.     public Rigidbody2D RBM; // RigidBody to Move
    9.     Stopwatch sw = new Stopwatch();
    10.     int movesPerFrame = 1;
    11.     int maxFrames = 500;
    12.  
    13.     int frames = 0;
    14.     bool resultsPrinted = false;
    15.     int x = 0;
    16.     int y = 0;
    17.  
    18.     void Update() {
    19.         if (frames++ < maxFrames)
    20.         {
    21.             sw.Start();
    22.             for (int i = 0; i < movesPerFrame; i++)
    23.             {
    24.                 TTT.position = new Vector3(x++, y++);
    25.                 //TTT.Translate(new Vector3(1, 1));
    26.                 //RBM.position = new Vector2(x++, y++);
    27.                 //RBM.MovePosition(new Vector2(x++, y++));
    28.             }
    29.             sw.Stop();
    30.         }
    31.         else
    32.         {
    33.             if (!resultsPrinted)
    34.             {
    35.                 UnityEngine.Debug.Log(string.Format(
    36.                     "Ticks: {0}, Ms: {1}, Elapsed: {2}\n" +
    37.                     "in {3} frames, {4} movements per frame.",
    38.                     sw.ElapsedTicks, sw.ElapsedMilliseconds, sw.Elapsed, maxFrames, movesPerFrame));
    39.                 resultsPrinted = true;
    40.             }
    41.         }
    42.     }
    43. }
    44.  
     
    Harinezumi, XRenkoX and angrypenguin like this.