Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

reset rigidbody

Discussion in 'iOS and tvOS' started by VIC20, Jan 28, 2010.

  1. VIC20

    VIC20

    Joined:
    Jan 19, 2008
    Posts:
    2,687
    How can i reset all forces of a rigidbody? Is deactivating the GameObject the only way?
     
  2. VIC20

    VIC20

    Joined:
    Jan 19, 2008
    Posts:
    2,687
    Anyone?
     
  3. rocket5tim

    rocket5tim

    Joined:
    May 19, 2009
    Posts:
    242
    Setting isKinematic to true will cause the rigidbody to stop moving under force and (as near as I can tell) reset/clear the forces.

    Code (csharp):
    1. rigidbody.isKinematic = false; // rigidbody can move under force
    2. rigidbody.AddForce(Vector3(0,1,0) * 50);
    3. yield WaitForSeconds(1);
    4. rigidbody.isKinematic = true; // stop!
    There may be a smarter way to do it tho... and of course your object will stop abruptly/unrealistically.
     
  4. VIC20

    VIC20

    Joined:
    Jan 19, 2008
    Posts:
    2,687
    the kinematic thing ends with weird slow physics after a while
     
  5. VIC20

    VIC20

    Joined:
    Jan 19, 2008
    Posts:
    2,687
    I really just want to reuse the object quickly - like it was respawned. But the only way to reset the rigidbody seems to destroy it. :?
     
  6. mudloop

    mudloop

    Joined:
    May 3, 2009
    Posts:
    1,107
    Can't you just set velocity and angularVelocity to new Vecttor3(0,0,0) ?
     
  7. VIC20

    VIC20

    Joined:
    Jan 19, 2008
    Posts:
    2,687
    No when i do this it ends with weird physics like it happens when setting it to kinematic and back - the objects start spinning more and more for no reason.

    seems like

    does not mean unrealistic behavior because of the scripts action itself but because physx don't like it at all.
     
    NEVER-SETTLE likes this.
  8. mudloop

    mudloop

    Joined:
    May 3, 2009
    Posts:
    1,107
    Hmm, I think I have done it before the way I described and it seemed to work. Do you have other things that might influence the rigidbodies, like joints, constant forces, etc? Are you respawning on the same frame?
    Maybe you can try setting drag and angular drag very high for a short while?
     
  9. VIC20

    VIC20

    Joined:
    Jan 19, 2008
    Posts:
    2,687
    After reset I'm adding torque to them - i see no way to reset this without destroying the rigidbody
     
  10. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    You might get the right result with rigidbody.Sleep, but it can sometimes do weird things if, say, the object is falling at the time it sleeps.
     
  11. markhula

    markhula

    Joined:
    Sep 3, 2011
    Posts:
    630
    Yep - I need also a definite way to 'reset' a rigid body back to it's defaults so that I can reuse it (rather than destroy it)

    Cheers
     
  12. Velvety

    Velvety

    Joined:
    May 4, 2009
    Posts:
    153
    I do something similar to "pause" physics controlled balls in my game (mid air) when I pull down the menu, and then reapply their forces when I unpause. I came across that weirdness of slow physics after a while, which was really finicky to work around. But here is what I found after much trial and error:

    - setting isKinematic to true will remove all movement and cause your object to "pause" as desired. So record it's current velocities first in order to reapply them after unpausing.
    - don't Sleep() the object because that seems to cause the slow physics after a while under some strange circumstances.
    - before you reset isKinematic to false, deactivate then activate the gameobject (this seems to prevent the slow physics as long as Sleep() is avoided).

    Here is pseudo code that I use for pausing and unpausing:

    Code (csharp):
    1.  
    2. // pause
    3.                // record the ball's current velocity make it pause/float mid-air
    4.                savedPauseVelocity = myRigidbody.velocity;
    5.                savedPauseAngularVelocity = myRigidbody.angularVelocity;
    6.                if (myRigidbody.isKinematic == false) {
    7.                        myRigidbody.velocity = Vector3.zero;
    8.                        myRigidbody.angularVelocity = Vector3.zero;
    9.                }
    10.                myRigidbody.useGravity = false;
    11.                myRigidbody.isKinematic = true;
    12.  
    13.  
    14. // unpause
    15.                        // to fix that prob where changing iskinematic can make the balls appear to drag, deactivate then
    16.                        // activate the ball which seems to fix it
    17.                        gameObject.active = false;
    18.                        gameObject.active = true;
    19.                        myRigidbody.useGravity = true;
    20.  
    21.                        myRigidbody.isKinematic = false;
    22.                        myRigidbody.velocity = savedPauseVelocity;
    23.                        myRigidbody.angularVelocity = savedPauseAngularVelocity;
    24.  
    25.  
     
  13. Risine

    Risine

    Joined:
    Dec 10, 2009
    Posts:
    154
    _AddForce( -velocity, ForceMode.VelocityChange);

    get the relative torque from angular velocity and :
    _AddRelativeTorque(-torque, ForceMode.VelocityChange);

    This way, you don't "break" the physic simulation.
     
  14. markhula

    markhula

    Joined:
    Sep 3, 2011
    Posts:
    630
    @Risine,

    Hey, thanks for the help all. But please explain exactly how I get the relative torque?

    Cheers
     
  15. markhula

    markhula

    Joined:
    Sep 3, 2011
    Posts:
    630
    Ok, I'm still failing on this :-(
    My rag doll is initially non-kinematic.
    So I guess I need to make it kinematic, reset each rigid body and then make it non-kinematic again???
    I've tried a yield return null (stall for 1 frame) between setting it kinematic and non-kinematic as I assume the physics needs an update to allow for this.
    Any suggestions on a reliable way to alter a kinematic/non-kinematic and 'do stuff' on the body before continuing?

    çheers
     
  16. Velvety

    Velvety

    Joined:
    May 4, 2009
    Posts:
    153
    Did you try or look at the pause/unpause code I shared above? This might help.
     
  17. markhula

    markhula

    Joined:
    Sep 3, 2011
    Posts:
    630
    Yeah.
    I'm trying to recycle objects hence the problem.
    I tried the yield after altering their state but it doesn't feet to work.
    Also altering velocity while kinematic complains it should be non-kinematic! (I would of thought the opposite!!)
    Here's what I do per rigid body:

    limb.rigidbody.isKinematic = true;
    yield return null;
    limb.rigidbody.velocity = Vector3.zero;
    limb.rigidbody.angularVelocity = Vector3.zero;
    limb.rigidbody.inertiaTensorRotation = Quaternion.identity;
    limb.rigidbody.inertiaTensor = Vector3.zero;
    limb.rigidbody.isKinematic = false;
    yield return null;

    I assume this make kinematic; I alter everything, and then allow non-kinematic again.
    Apparently I can't set the velocity this way - and I'm not convinced the yields do as I expect......

    Cheers
     
  18. Velvety

    Velvety

    Joined:
    May 4, 2009
    Posts:
    153
    You can't change the velocity and stuff when iskinematic = true. Try doing it in this order:

    limb.rigidbody.velocity = Vector3.zero;
    limb.rigidbody.angularVelocity = Vector3.zero;
    limb.rigidbody.inertiaTensorRotation = Quaternion.identity;
    limb.rigidbody.inertiaTensor = Vector3.zero;
    limb.rigidbody.isKinematic = true;
    limb.rigidbody.isKinematic = false;

    I'm not sure setting isKinemetic to true and then false is even necessary. I do it in my pause/unpause code because I want my paused objects to hang mid-air while the user does stuff in the menu (ie: frames happen while it is paused). But it looks like you are just immediately removing velocities and that is it - so changing isKinematic may not be necessary?
     
  19. markhula

    markhula

    Joined:
    Sep 3, 2011
    Posts:
    630
    Did exactly as you said and get

    Supplied NxActorDec is not valid.createActor returns NULL. this occurs on setactiverecursively.
    here's my full code:

    Code (csharp):
    1.  
    2.  
    3. void init()
    4.     {
    5.         character2 = transform.parent.Find("character2");
    6.         //print(character2);
    7.        
    8.         Color newColor = character2.renderer.material.color;
    9.         newColor.a = 1;
    10.         character2.renderer.material.color = newColor;
    11.        
    12.         Transform limb = gameObject.transform; //biped
    13.         RESET(limb);
    14.         limb = transform.Find("L Thigh");
    15.         RESET(limb);
    16.         limb = limb.transform.Find("L Calf");
    17.         RESET(limb);
    18.         limb = transform;
    19.         limb = transform.Find("R Thigh");
    20.         RESET(limb);
    21.         limb = limb.transform.Find("R Calf");
    22.         RESET(limb);
    23.         limb = transform;
    24.         limb = transform.Find("Spine/Spine1");
    25.         RESET(limb);
    26.         limb = transform.Find("Spine/Spine1/Spine2/Head");
    27.         RESET(limb);
    28.         limb = transform.Find("Spine/Spine1/Spine2/L UpperArm");
    29.         RESET(limb);
    30.         limb = transform.Find("Spine/Spine1/Spine2/L UpperArm/L Forearm");
    31.         RESET(limb);
    32.         limb = transform.Find("Spine/Spine1/Spine2/R UpperArm");
    33.         RESET(limb);
    34.         limb = transform.Find("Spine/Spine1/Spine2/R UpperArm/R Forearm");
    35.         RESET(limb);
    36.        
    37.         //rigidbody.AddForce(-rigidbody.velocity,ForceMode.VelocityChange);
    38.         //rigidbody.AddRelativeTorque(-rigidbody.tor
    39.         //rigidbody.isKinematic = true;
    40.    
    41.         //rigidbody.isKinematic = false;
    42.         //rigidbody.velocity = Vector3.zero;
    43.         //rigidbody.angularVelocity = Vector3.zero;
    44.        
    45.         //print(transform.position);
    46.     }
    47.    
    48.     void RESET(Transform limb)
    49.     {
    50.         //return;
    51.         if (limb == null)
    52.             print("NULL");
    53.        
    54.         print("LIMB:"+limb.name);
    55.         limb.rigidbody.velocity = Vector3.zero;
    56.         limb.rigidbody.angularVelocity = Vector3.zero;
    57.         limb.rigidbody.inertiaTensorRotation = Quaternion.identity;
    58.         limb.rigidbody.inertiaTensor = Vector3.zero;
    59.         limb.rigidbody.isKinematic = true;
    60.         limb.rigidbody.isKinematic = false;
    61.     }
    62.  
    63.  
     
  20. Velvety

    Velvety

    Joined:
    May 4, 2009
    Posts:
    153
    I'm not sure what that error is about, but I don't think it's happening in the RESET function, maybe it's happening in one of the Find calls? Does it say what line the error is happening on?
     
  21. markhula

    markhula

    Joined:
    Sep 3, 2011
    Posts:
    630
    The error is return in pool manager at a recursive enable function call.
     
  22. UserX

    UserX

    Joined:
    Nov 7, 2012
    Posts:
    12
    Hey guys, this thread was a big help to me..just thought I'd share my C# solution, using CoRoutines.
    Its working perfectly for me and solves the rigidbody.isKinematic physics problem.
    In my case I'm giving the object a new force (same magnitude) in a random direction after stopping it.
    Hope it helps people in the future :)

    All these code snippets are in the script attached to the object:

    Code (csharp):
    1. Vector3 eulers = Vector3.zero;
    2. private bool waiter;
    Code (csharp):
    1. IEnumerator shotRedirect()
    2.     {
    3.         yield return new WaitForSeconds(0.0f);
    4.         eulers = transform.eulerAngles;
    5.         eulers.x = Random.Range(0,360);
    6.         transform.eulerAngles = eulers;
    7.         rigidbody.isKinematic = true;  
    8.         StartCoroutine(shotRedirectPart2());
    9.     }
    10.    
    11. IEnumerator shotRedirectPart2()
    12.     {
    13.         yield return new WaitForSeconds(0.01f);
    14.         rigidbody.isKinematic = false;
    15.         rigidbody.AddForce(transform.forward * shotPower);
    16.     }
    17.  

    Code (csharp):
    1.    
    2. private void Waits()
    3.     {
    4.         waiter = true;
    5.     }
    6.    
    7. void Update()  
    8.     {
    9.         if(waiter == true)
    10.         {
    11.             if (Input.GetKeyDown(KeyCode.A))
    12.             {      
    13.                 StartCoroutine(shotRedirect());
    14.             }
    15.             waiter = false;
    16.             Invoke("Waits",0f);
    17.         }
    18. ]
     
    Last edited: Jul 23, 2013
  23. Alleck

    Alleck

    Joined:
    Nov 19, 2014
    Posts:
    1
    This is exactly what I needed. Thank you much!
     
  24. Anisoropos

    Anisoropos

    Joined:
    Jul 30, 2012
    Posts:
    102
    In my case all I needed to stop and respawn an object was the following:

    Code (CSharp):
    1. IEnumerator Reset(Rigidbody rB, Vector3 targetPos, Quaternion targetRot)
    2.     {
    3.         rB.velocity = Vector3.zero;
    4.         rB.angularVelocity = Vector3.zero;
    5.  
    6.         yield return new WaitForFixedUpdate();
    7.  
    8.         // Transport it
    9.         rB.transform.position = targetPos;
    10.         rB.transform.rotation = targetRot;
    11.     }
     
  25. NEVER-SETTLE

    NEVER-SETTLE

    Joined:
    Apr 22, 2018
    Posts:
    30
    // EDIT: AAaaaand I spoke too soon, the workaround didn't work....around, I found cases where the car still flips....


    I also ran into a similar issue. The scenario is in a racing game. I hit pause game (timescale =0) while drifting the car to the right. Then hit reset, which should reset the position to a certain point (and timescale=1). This point is suspended in the air. The problem is that even tough I tried ALL of the code above, my car had so much force applied to it from drifting to the right that it flipped (rotated)in mid air upon reset. Again, I tried each and every solution from above and the car still keeps inertia somehow...

    A workaround I did was to modify Anisoropos code and stop the velocity and angularVelocity again after positioning the car.

    Code (CSharp):
    1. IEnumerator Reset(Rigidbody rB, Vector3 targetPos, Quaternion targetRot)
    2.     {
    3. // Stop the car
    4.         rB.velocity = Vector3.zero;
    5.         rB.angularVelocity = Vector3.zero;
    6.         yield return new WaitForFixedUpdate();
    7.  
    8.         // Transport it, the fkin S*** flips in mid air
    9.         rB.transform.position = targetPos;
    10.         rB.transform.rotation = targetRot;
    11.         yield return new WaitForFixedUpdate();
    12.  
    13. // Stop the car again, this results in only a very very slight inertia, not enough to flip it
    14.         rB.velocity = Vector3.zero;
    15.         rB.angularVelocity = Vector3.zero;
    16.         yield return new WaitForFixedUpdate();
    17.     }
     
    Last edited: Jan 10, 2019