With Unity old animation system you could make speed = -1
and animation will play backwards - so easy! But with new mecanim you cannot do this — if you make negative animator speed you will get error in console.
In my scenario I have tutorial animation with 6 slides, on each slide player have buttons «prev» and «next» so it can move forward an backward between slides with nice animation. Because mecanim cannot do backward animation, I had to write comlex script to manage each frame of animation on Update(). Here it is and I hope It will help someone:
using UnityEngine;
public class Tutorial : MonoBehaviour
{
const float slidePeriod = 1 / 3f;
Animator animator;
int stateHash;
float curAnimTime;
float totalAnimTime;
float nextSlideTime;
bool playForward;
void Start()
{
transform.localPosition = Vector3.zero;
animator = GetComponent<Animator>();
stateHash = animator.GetCurrentAnimatorStateInfo(0).tagHash;
totalAnimTime = slidePeriod * 5; //animator.runtimeAnimatorController.animationClips[0].length;
animator.speed = 0;
enabled = false;
if (PlayerPrefs.GetInt("tutorialShown", 0) == 0)
Show();
else
gameObject.SetActive(false);
}
void Update()
{
if (playForward)
{
curAnimTime += Time.unscaledDeltaTime;
if (curAnimTime > nextSlideTime)
{
curAnimTime = nextSlideTime;
enabled = false;
}
}
else
{
curAnimTime -= Time.unscaledDeltaTime;
if (curAnimTime < nextSlideTime)
{
curAnimTime = nextSlideTime;
enabled = false;
}
}
animator.Play(stateHash, 0, curAnimTime/totalAnimTime);
}
public void PlayForward()
{
playForward = true;
nextSlideTime += slidePeriod;
if (nextSlideTime > totalAnimTime)
nextSlideTime = totalAnimTime;
enabled = true;
}
public void PlayBackwards()
{
playForward = false;
nextSlideTime -= slidePeriod;
if (nextSlideTime < 0)
nextSlideTime = 0;
enabled = true;
}
public void ShowSlide(int slideNo)
{
curAnimTime = nextSlideTime = slidePeriod * slideNo;
enabled = false;
animator.Play(stateHash, 0, curAnimTime/totalAnimTime);
}
public void Show()
{
gameObject.SetActive(true);
ShowSlide(0);
}
public void Done()
{
PlayerPrefs.SetInt("tutorialShown", 1);
gameObject.SetActive(false);
}
}