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): rigidbody.isKinematic = false; // rigidbody can move under force rigidbody.AddForce(Vector3(0,1,0) * 50); yield WaitForSeconds(1); rigidbody.isKinematic = true; // stop! There may be a smarter way to do it tho... and of course your object will stop abruptly/unrealistically.
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. :?
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.
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?
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.
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
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): // pause // record the ball's current velocity make it pause/float mid-air savedPauseVelocity = myRigidbody.velocity; savedPauseAngularVelocity = myRigidbody.angularVelocity; if (myRigidbody.isKinematic == false) { myRigidbody.velocity = Vector3.zero; myRigidbody.angularVelocity = Vector3.zero; } myRigidbody.useGravity = false; myRigidbody.isKinematic = true; // unpause // to fix that prob where changing iskinematic can make the balls appear to drag, deactivate then // activate the ball which seems to fix it gameObject.active = false; gameObject.active = true; myRigidbody.useGravity = true; myRigidbody.isKinematic = false; myRigidbody.velocity = savedPauseVelocity; myRigidbody.angularVelocity = savedPauseAngularVelocity;
_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.
@Risine, Hey, thanks for the help all. But please explain exactly how I get the relative torque? Cheers
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
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
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?
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): void init() { character2 = transform.parent.Find("character2"); //print(character2); Color newColor = character2.renderer.material.color; newColor.a = 1; character2.renderer.material.color = newColor; Transform limb = gameObject.transform; //biped RESET(limb); limb = transform.Find("L Thigh"); RESET(limb); limb = limb.transform.Find("L Calf"); RESET(limb); limb = transform; limb = transform.Find("R Thigh"); RESET(limb); limb = limb.transform.Find("R Calf"); RESET(limb); limb = transform; limb = transform.Find("Spine/Spine1"); RESET(limb); limb = transform.Find("Spine/Spine1/Spine2/Head"); RESET(limb); limb = transform.Find("Spine/Spine1/Spine2/L UpperArm"); RESET(limb); limb = transform.Find("Spine/Spine1/Spine2/L UpperArm/L Forearm"); RESET(limb); limb = transform.Find("Spine/Spine1/Spine2/R UpperArm"); RESET(limb); limb = transform.Find("Spine/Spine1/Spine2/R UpperArm/R Forearm"); RESET(limb); //rigidbody.AddForce(-rigidbody.velocity,ForceMode.VelocityChange); //rigidbody.AddRelativeTorque(-rigidbody.tor //rigidbody.isKinematic = true; //rigidbody.isKinematic = false; //rigidbody.velocity = Vector3.zero; //rigidbody.angularVelocity = Vector3.zero; //print(transform.position); } void RESET(Transform limb) { //return; if (limb == null) print("NULL"); print("LIMB:"+limb.name); 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 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?
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): Vector3 eulers = Vector3.zero; private bool waiter; Code (csharp): IEnumerator shotRedirect() { yield return new WaitForSeconds(0.0f); eulers = transform.eulerAngles; eulers.x = Random.Range(0,360); transform.eulerAngles = eulers; rigidbody.isKinematic = true; StartCoroutine(shotRedirectPart2()); } IEnumerator shotRedirectPart2() { yield return new WaitForSeconds(0.01f); rigidbody.isKinematic = false; rigidbody.AddForce(transform.forward * shotPower); } Code (csharp): private void Waits() { waiter = true; } void Update() { if(waiter == true) { if (Input.GetKeyDown(KeyCode.A)) { StartCoroutine(shotRedirect()); } waiter = false; Invoke("Waits",0f); } ]
In my case all I needed to stop and respawn an object was the following: Code (CSharp): IEnumerator Reset(Rigidbody rB, Vector3 targetPos, Quaternion targetRot) { rB.velocity = Vector3.zero; rB.angularVelocity = Vector3.zero; yield return new WaitForFixedUpdate(); // Transport it rB.transform.position = targetPos; rB.transform.rotation = targetRot; }
// 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): IEnumerator Reset(Rigidbody rB, Vector3 targetPos, Quaternion targetRot) { // Stop the car rB.velocity = Vector3.zero; rB.angularVelocity = Vector3.zero; yield return new WaitForFixedUpdate(); // Transport it, the fkin S*** flips in mid air rB.transform.position = targetPos; rB.transform.rotation = targetRot; yield return new WaitForFixedUpdate(); // Stop the car again, this results in only a very very slight inertia, not enough to flip it rB.velocity = Vector3.zero; rB.angularVelocity = Vector3.zero; yield return new WaitForFixedUpdate(); }