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 Answer 1

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.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .