Whenever I try to reset a (non-looping) AnimationClipPlayable, the animation plays an event near the end of the clip before starting from the beginning. It also plays an event that occurs near the beginning of the clip twice!
I have no idea why this is occurring. Below is the script that plays animations. Please focus on PlayAnimation, as that is the function responsible for selecting a clip by setting its weight to 1.0 in the mixer and setting its time to 0.0. I also set the mixer’s time to 0.0, but that may not be necessary.
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Animations;
using System.Collections.Generic;
/// <summary>
/// Animator for character. Uses Unity's Playable API.
/// </summary>
public class SpriteAnimator : MonoBehaviour {
[SerializeField]
private AnimationClip[] animationClips;
[SerializeField]
private int defaultClipIndex = 0;
[SerializeField]
private SpriteRenderer SpriteRenderer;
private PlayableGraph playableGraph;
private AnimationMixerPlayable mixerPlayable;
private Dictionary<string, int> clipNameToIndex = new
Dictionary<string, int>();
private AnimationClipPlayable[] clipPlayables;
private int currentClipIndex = 0;
public SpriteRenderer SpriteAnimRenderer { get; private set; }
public void Initialize() {
for (int clipIndex = 0; clipIndex < animationClips.Length; clipIndex++) {
var animationClip = animationClips[clipIndex];
clipNameToIndex.Add(animationClip.name, clipIndex);
}
SpriteAnimRenderer = SpriteRenderer;
}
private void OnEnable() {
currentClipIndex = defaultClipIndex;
CreatePlayableGraph();
}
private void CreatePlayableGraph() {
playableGraph = PlayableGraph.Create();
playableGraph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);
var playableOutput = AnimationPlayableOutput.Create(playableGraph,
"SpriteAnimationPlayableOutput", GetComponent<Animator>());
int numClips = animationClips.Length;
mixerPlayable = AnimationMixerPlayable.Create(playableGraph,
numClips);
clipPlayables = new AnimationClipPlayable[numClips];
playableOutput.SetSourcePlayable(mixerPlayable);
for (int clipIndex = 0; clipIndex < numClips; clipIndex++) {
var animationClip = animationClips[clipIndex];
// TODO: make this work for non-looping animations
var clipPlayable = AnimationClipPlayable.Create(playableGraph,
animationClip);
playableGraph.Connect(clipPlayable, 0, mixerPlayable, clipIndex);
clipPlayables[clipIndex] = clipPlayable;
mixerPlayable.SetInputWeight(clipIndex, 0.0f);
}
mixerPlayable.SetInputWeight(currentClipIndex, 1.0f);
playableGraph.Play();
}
private void OnDisable() {
mixerPlayable.Destroy();
playableGraph.Destroy();
}
/// <summary>
/// Play the requested clip while disabling the rest.
/// </summary>
/// <param name="requestedClipName">Requested clip name.</param>
public void PlayAnimation(string requestedClipName) {
int requestedClipIndex;
if (clipNameToIndex.TryGetValue(requestedClipName,
out requestedClipIndex)) {
if (currentClipIndex == requestedClipIndex) {
return;
}
for (int clipIndex = 0; clipIndex < animationClips.Length;
clipIndex++) {
mixerPlayable.SetInputWeight(clipIndex,
(clipIndex == requestedClipIndex) ? 1.0f : 0.0f);
}
mixerPlayable.Pause();
clipPlayables[requestedClipIndex].SetTime(0.0f);
Debug.Log("lead time: " + mixerPlayable.GetLeadTime());
Debug.Log("clip play time: " + clipPlayables[requestedClipIndex].GetTime());
mixerPlayable.SetTime(0.0);
mixerPlayable.Play();
currentClipIndex = requestedClipIndex;
}
else {
Debug.LogWarningFormat("Could not find clip named {0} on " +
"sprite animator on game object named {1}.", requestedClipName,
this.name);
}
}
// TODO: get current time normalized
public double GetAnimationTime(){
return mixerPlayable.GetTime();
}
}
I’ve searched online and there isn’t a whole lot of documentation about this or the bug that is occurring. This question has been asked before – I don’t remember where the specific thread is but it looks like the poster didn’t get any responses. Hopefully I have better luck since the playable system seems to be the best way to programmatically control animations. It’s either my script or maybe the animation itself is buggy.