Is it possible to cleanly reset a ragdoll? (all it’s joints/rigidbodies?)
I’ve got a character that switches between Mecanim-animation-controlled and ragdoll, by disabling the animator and switching the ragdoll bodies isKinematic on/off. Everything works fine the first time, with a nice transition from animation to ragdoll.
Now I want to pool/recycle characters, as instantiation causes a big performance spike. But I’m having trouble resetting the ragdoll nodes ready to use again. It appears as either the joints are misbehaving when the ragdoll is enabled the second time, or the rigidbodies still have some velocity/force being applied - as some bones, particularly the characters arms, snap immediately to odd positions.
It doesn’t look ‘completely broken’, but there’s clearly something not quite right.
I’m currently zeroing the velocity/angularVelocity on the rigidbodies, but I’m not doing anything to the joints. Do these need resetting, and if so, how? (the node positions are obviously all updated by the Animator, so the ragdoll starts in a valid state - although different positions from the first time that it was enabled)
Has anyone else encountered problems resetting ragdolls (or other other objects with physics joints?)
Yes, I have had this problem with rigidbodies, and resetting the velocity / angularvelocity didn’t work for me. What DID work was setting the Rigidbody “IsKinematic” to true to turn it off, and then false to turn back on. I recall it not working if it happened all during the same update call (maybe something is triggered afterward to clean up). But it worked if it happened in subsequent frames.
I’ve read that setting IsKinematic to true should zero the rigidBody’s momentum - but all my bodies are being set back to IsKinematic whilst the character is animating (which works fine on ‘recycled’ character instances).
Maybe it’s something to do with the joints themselves? - can’t see any obviously-resettable state on those, though…
Strangely, this problem only seems to occur if the gameobject is turned off when the ragdoll components are enabled, then on again.
If I never turn it off, I can repeatedly switch between ragdoll and animation mode without the problem. If I only turn it on and off when in animation mode, it’s fine. But if I turn if off in ragdoll mode, then back on, the next time it switches the ragdoll mode, there appears to be unwanted motion (unwanted forces/velocities?/bad joint behaviour? - I’m still not sure exactly which)
(I’m running a minimal test scene now, too - with all scripts removed except for my ‘ragdoll toggler’…)
Well, I found a workaround, but have absolutely no idea why it works/what causes the problem.
Before turning off my character with SetActive(false), I turn the Animator back on for one frame, with the ragdoll bodies set to isKinematic=true, and the render meshes hidden, to hide the glitch that this would create.
For some inexplicable reason, this prevents the problem from occuring. Very strange.
The previous workaround didn’t really work - it made things less-broken-looking, but wasn’t actually a fix.
I’ve now found out what’s going on. It seems that disabling then re-enabling a character causes its joints to be re-initialized in an undesirable way, losing their ‘home position’.
If you set all the swing/twist limits to zero, the character should spring into his T-pose when the ragdoll is enabled, as the joints were set up relative to the T-pose in the editor. This works fine if the character has never been disabled/re-enabled.
But if the character is turned off with SetActive(), then back on again, it doesn’t snap to the T-pose next time the ragdoll is enabled. It appears tha it springs back to the position that the bones were in when the character was last disabled. The ‘home position’ of the joints has been changed, undesirably. (I think this is a bug in Unity, it doesn’t seem very useful behaviour?)
This explains why the ragdoll goes wrong/‘floppy’ - the twist/swing constraints are being enforced relative to an incorrect starting position.
There seems to be a simple solution, though:
On Awake(), store the local transform of all bones (which will be the original T-pose transforms)
On OnDisable(), restore these transforms
This seems to prevent the joints from being incorrectly reset/reinitialized.
We tried this but did not work in out instance HOWEVER we did find the cause of our problems and the solution. It was due to the interpolation being set.
So what has now worked is when we disable the character at the start of the level we set
RigidbodyInterpolation.None;
When we enable character
RigidbodyInterpolation.Interpolate;
I found that after hide the character then show it in heirarchy, the ragdoll works right again.
so, i do
characterJoint.gameObject.SetActive(false);
characterJoint.gameObject.SetActive(true);
and set
rigidbody.isKinematic = true;
i solved the problem in this way. maybe joint is reset in OnEnable.
This post helped me.
I disabled the rigidbodies for some period of time (rigidbody.gameobject.SetActive(false)) and reenabled, so now my ragdoll is pretty stabile.
I’ve been struggling with this too. In my case, my character is never inactive. It’s a goalkeeper that is either animated or ragdolled.
I was able to get it working, at least 90% of the time, by first disabling the root game object of my character, then applying my cached positions and rotations (done on awake). I do this within the span of a single frame, and it seems to work a lot better than what it did before.