Check when rotation of child object has stopped?
I am trying to find when the rotation of a child joint on a hand rig has stopped moving. I need to know when it has stopped so I can hide the hand. (leap motion controller w/ multi player issue)
The item is kinematic so I cant check velocity
//All the multiplayer stuff works I just cant hide the hand
netLeftPalm.transform.position = localLeftPalm.transform.position;
netLeftPalm.transform.rotation = localLeftPalm.transform.rotation;
//Fails as kinematic rigidbodys are always zero and gravity is always falling
Rigidbody sleeper = netLeftPalm.GetComponent<Rigidbody>();
if (sleeper.velocity.sqrMagnitude < stopThreshold && sleeper.angularVelocity.sqrMagnitude < stopThreshold)
{
//Works on mesh renderer or skinned mesh
netLeftHand.transform.localScale = Vector3.zero;
}
else
{
netLeftHand.transform.localScale = Vector3.one;
} ...
using a kinematic rigid body I can check if its sleeping but its not good:
if (netLeftPalm.GetComponent<Rigidbody>().IsSleeping())
{
//by scaling the root object when the leap motion losses tracking the hands disappear rather then being left floating disembodied.
// This however seems to cause issues with the rig stretching and bouncing before it disappears.
//If done on a single object however this works fine just not on a rigged object.
netLeftHand.transform.localScale = new Vector3(0, 0, 0);
}
else
{
//Note: also tried to force uniform scaling with the same result, still its the best so far.
netLeftHand.transform.localScale = Vector3.one;
} ...
Trying to disable the object or turn off its render has also failed over the network but the joints positions work fine when using if(isLocal)...
//Simply setting the root hand to active leaves it floating for some reason
netLeftHand.SetActive(false);
//same thing when disabling the renderer so this is not syncing over the network
netLeftHand.GetComponentInChildren<SkinnedMeshRenderer>().enabled = false;
I tried using .haschanged
//No dice. Seems like it should work as the rotation changes while the hand is in frame and stops when its not.
if (netLeftPalm.transform.hasChanged)
{
netLeftHand.transform.localScale = Vector3.zero;
transform.hasChanged = false;
}
else
{
netLeftHand.transform.localScale = Vector3.one;
transform.hasChanged = true;
}
I tried some rotation script but had issues.
//speaking of dice lets try tracking the roll... Doesn't work as its slow causing lag and reads the wrong objects rotation.
currentRotation = netLeftPalm.transform.rotation;
if (Mathf.Abs(Quaternion.Angle(rotationStored, netLeftPalm.transform.rotation)) < maxErrorAllowedPerFrame || currentRotation == rotationStored)
{
inRange = true;
}
else
{
inRange = false;
}
rotationStored = netLeftPalm.transform.rotation;
if (inRange)
{
netLeftHand.transform.localScale = Vector3.zero;
}
else
{
netLeftHand.transform.localScale = Vector3.one;
} ...
Any ideas on how I can get the rotation of the child joint when the transform position is not changing and the rotation is not effecting the velocity?
if (Mathf.Abs(oldEulerAngles.x - netLeftHand.transform.rotation.eulerAngles.x)<stopThreshold)
{
//NO ROTATION
netLeftHand.transform.localScale = Vector3.zero;
}
else
{
Mathf.Abs(oldEulerAngles.x - netLeftHand.transform.rotation.eulerAngles.x);
//ROTATION
netLeftHand.transform.localScale = Vector3.one;
}
Fails to ever scale to one and if you remove the Math.Abs and .x it flickers between one and zero making the hand stretch again like it does with the rigidbody.isSleeping test. My best guess is that its seeing rotation on the parent as well as the rotation of the specified game object.
Edit: Testing with the MathF.Abs it stretches the hand in and out with a threshold of 0.000001f
2nd Edit: I just realized I was using the hand rotation in this test and when using the palm rotation it works better with a stop threshold of .001 Its almost right but still gives me the stretchy hand every now and then.
This seemed to work in a local test but does not work when networked
if (Mathf.Abs(oldRightEulerAngles.x - netRightPalm.transform.rotation.eulerAngles.x) < stopThreshold)
{
//NO ROTATION
netLeftHand.GetComponentInChildren<SkinnedMeshRenderer>().enabled = false;
}
else
{
oldRightEulerAngles = netRightPalm.transform.rotation.eulerAngles;
//ROTATION
netLeftHand.GetComponentInChildren<SkinnedMeshRenderer>().enabled = true;
}
Using the Mathf.Abs soutuion above I and calling CmdLeftHandDisable(); or CmdLeftHandEnable(); with:
[Command]
void CmdLeftHandEnable()
{
if (isClient) netLeftHand.gameObject.SetActive(true);
else RpcLeftHandEnable();
}
[ClientRpc]
void RpcLeftHandEnable()
{
netLeftHand.gameObject.SetActive(true);
}
[Command]
void CmdLeftHandDisable()
{
if (isClient && isLocalPlayer) netLeftHand.gameObject.SetActive(false);
else RpcLeftHandDisable();
}
[ClientRpc]
void RpcLeftHandDisable()
{
netLeftHand.gameObject.SetActive(false);
Debug.Log("Left Hand Disable");
}
Works perfectly for the client but the Host gets really screwed up. I think I will need to open a new networking question.