- Home /
How to detect end of slerp when moving bone
I am trying to animate a bone procedurally when it is right-clicked. The code animates the bone to its lower position, then back to its upper (original) position. But the test to determine whether it has reached the upper position doesn't work. The calculated angle between the bone's position and the target goes to zero when the bones is driven down to the lower position, but when it is driven back up it never goes below about 25 degrees.
I have also tried testing for equality between the bone position and target (i.e. if (target == myAbsoluteBoneRotation) ...) but with similar results: the down test works, the up test doesn't, even though the reported values are identical. (Perhaps there is a precision issue here though.)
Any idea what is going on? All suggestions most gratefully received...
public class BoneController : MonoBehaviour {
// get the transform of the bone
public Transform _bone;
// store absolute rotation
private Quaternion myAbsoluteBoneRotation;
// hold rotations
private Quaternion myBoneRotation;
// control animation sequence
private bool animatingBone = false;
private bool animationDirectionUp = false;
private const float animationSpeed = 5.0f;
// targets
private Quaternion target;
private Quaternion upTarget;
private Quaternion downTarget;
void Start () {
// the two positions of the bone
upTarget = new Quaternion(-0.2f, 0.3f, 0.0f, -0.9f);
downTarget = new Quaternion(-0.2f, -0.2f, -0.1f, -1.0f);
// initialise to bone's position
myAbsoluteBoneRotation = _bone.rotation;
}
void LateUpdate() {
// if the right mouse button is down, move the bone
if (Input.GetMouseButtonDown(1)) {
animatingBone = true;
animationDirectionUp = false;
target = downTarget;
}
if (animatingBone) {
// find angle between actual position and target
float angle = Mathf.Abs(Quaternion.Angle(myAbsoluteBoneRotation, target));
if (animationDirectionUp) {
// check whether upper limit reached
if (angle > 0.0f) {
myAbsoluteBoneRotation = Quaternion.Slerp(myAbsoluteBoneRotation,
target, animationSpeed * Time.deltaTime);
} else {
// we have reached upper limit, so halt animation
animatingBone = false;
}
} else {
// check whether lower limit reached
if (angle > 0.0f) {
myAbsoluteBoneRotation = Quaternion.Slerp(myAbsoluteBoneRotation,
target, animationSpeed * Time.deltaTime);
} else {
// we have reached lower position, so start animation to upper position
animationDirectionUp = true;
target = upTarget;
}
}
// move the bone
_bone.rotation = myAbsoluteBoneRotation;
}
}
}
The best solution I have found so far is to time limit the up animation. So, in pseudo code:
when start up animation, reset timer
apply up animation while timer < some value
This is awful. Does anyone have a better solution?
Your answer
Follow this Question
Related Questions
Slerp with rotations from different spaces 0 Answers
Unity animator with blender bones causes gimbal lock. 1 Answer
Rotating Armature During Animation 1 Answer
Mouse Over Wont Work on Bone Animated Meshes. 1 Answer
Quaternion.Slerp 1 Answer