Adam Jonsson
Adam Jonsson

Reputation: 2244

Unity - How to interrupt an ongoing animation by reversing it

Context
I got two transform states on a GameObject, A and B. I also have two animations that transition between the two states: A->B and B->A. The animations have different animation curves. The user can change the state of the GameObject at any moment.

What I want to achieve
If the state is changed while no animations are playing, the animations A->B and B->A are played normally. However, if the state is changed while an animation is playing, I want the current animation to reverse. For example, let's say that the user changes the state to B, and the animation A->B starts playing. Then the user suddenly changes back to state A before the animation A->B has finished. Here I want the A->B animation to start reversing to state A again, not playing the animation B->A.

What I currently have
I have tried to use Unity's Animator but have found no function to reverse an ongoing animation. I am open to using something else than the Animator but prefer not to use any external libraries.

Here is the current code I have with no reverse logic, only changing between state A and B

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestAnimation : MonoBehaviour
{
    private Animator _animator;

    private bool _isOpen = true;

    void Awake()
    {
        this._animator = GetComponent<Animator>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            if (this._isOpen)
                this._animator.SetTrigger("A");
            else
                this._animator.SetTrigger("B");

            this._isOpen = !this._isOpen;
        }
    }
}

Upvotes: 0

Views: 1080

Answers (1)

Adam Jonsson
Adam Jonsson

Reputation: 2244

Found a solution now. Do not know if it is the most simple one but it works. What I did was to activate the animation by playing them via script, not using any triggers or floats in the animator as I tried first. I also created two new animation states that are the reversed version of A->Band B->A. I looked at the normelizedTime variable in the animator to determine if any animation was currently playing. If so, I played the reversed animation at where it ended, see the code below.

Here is the animator with the different animation states: A->B A->B Reversed B->A B->A Reversed

And here is the code

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestAnimation : MonoBehaviour
{
    private Animator _animator;

    private bool _toggle = true;

    private bool _isPlayingReverse = true;

    void Awake()
    {
        this._animator = GetComponent<Animator>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            var animationTime = Mathf.Clamp(this._animator.GetCurrentAnimatorStateInfo(0).normalizedTime, 0.0f, 1.0f);
            bool animationOngoing = animationTime < 1;

            if (this._toggle)
            {
                if (animationOngoing && !this._isPlayingReverse)
                {
                    this._animator.Play("A->B - Reversed", 0, 1 - animationTime);
                    this._isPlayingReverse = true;
                }
                else
                {
                    this._animator.Play("B->A", 0, 1 - animationTime);
                    this._isPlayingReverse = false;
                }
            }
            else
            {
                if (animationOngoing && !this._isPlayingReverse)
                {
                    this._animator.Play("B->A - Reversed", 0, 1 - animationTime);
                    this._isPlayingReverse = true;
                }
                else
                {
                    this._animator.Play("A->B", 0, 1 - animationTime);
                    this._isPlayingReverse = false;
                }
            }

            this._toggle = !this._toggle;
        }
    }
}

Upvotes: 0

Related Questions