- 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