1
\$\begingroup\$

I have an animation clip I want to play, using the object's x position to control which frame of the animation is displayed. ie.

  • When the object is at x = -2, the animation should show its initial frame.
  • As the object moves rightward (increasing x) the animation should play forward.
  • When the object is at x = 6, the animation should show its final frame.
  • As the object moves leftward (decreasing x) between these values, the animation should play in reverse.

I thinks this is a form of clamping where I want to map x values into key frames of the animation.

Below just a simple code to run animation:

void Update () {
    if (isPositionChanging)
    {
        if(transform.position.x > xPos){
            if(incrementOrDecrement <=12) {
            incrementOrDecrement ++;
            AnimationPlayOnPositionValue(1, incrementOrDecrement);
            }
        }
        else {
            if (incrementOrDecrement >= 0)
            {
            incrementOrDecrement--;
            AnimationPlayOnPositionValue(1, incrementOrDecrement);
            }
        }

    }
}

void AnimationPlayOnPositionValue(float speed,float timeToUpdate) {
    animatedObject["MachineAnimationComplete"].speed = speed;
    animatedObject["MachineAnimationComplete"].time = timeToUpdate;
    animatedObject.Play();

}
\$\endgroup\$
1
\$\begingroup\$

Here's a quick example using the AnimationClip.SampleAnimation method:

public class SampleByPosition : MonoBehaviour {

    public AnimationClip animationClip;

    // Direction in which a change in position should advance the animation.
    public Vector3 direction = Vector3.right;

    // Distances from the origin along this direction, 
    // corresponding to the beginning & ending frames of the animation.
    public float start = -2;
    public float end = 6;

    // Cache previous frame time to avoid redundant work.
    float _previousT = float.NegativeInfinity; 

    void Start () {
        // Normalizing the vector ensures our dot product below
        // returns distances in worldspace units, for ease of use.
        direction.Normalize();
    }

    // Animate in LateUpdate to include any motion in preceding Update.
    void LateUpdate () {

        // Calculate an animation time value from the object's position.
        float t = Vector3.Dot(transform.position, direction);
        t = animationClip.length * (t - start) / (end - start);

        // If this is the same time value we used last frame, bail out early.
        // (Sampling an animation has some performance cost, so if the frame
        //  we used recently is still valid, don't re-calculate it)
        if (Mathf.Approximately(t, _previousT))
            return;

        // Apply this moment of the animation to our host GameObject.
        animationClip.SampleAnimation(gameObject, t);

        // Cache the time value to compare against next frame.
        _previousT = t;
    }
}

Since we don't want to animate over time, but directly control the playhead in the clip, I skipped the Animation component entirely. If you want to blend multiple animations, the Animation.Sample method is better-suited - it's just a bit more verbose to set up if you only need a single clip.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.