• Runtimes
  • [Unity] Queue of multiple animations looped

  • Düzenlendi
Related Discussions
...

OK - so I have some nice animations for my characters in Spine, like:
Idle
Smiling
Blinking
Eyes left
Eyes right

I want to be able to sort of script these in a random sort of way and then have some overlaid in reaction to the user doing something.
So an example would be to play the blinking animation in a loop but with a random amount of time before restarting the loop - to give a more natural blinking.
Similarly, at the same time as the character is randomly blinking, I'd like to queue up some different facial animations like oooh, smile, laugh, to be played randomly as well with a random amount of time between them.

I'd also like to be able to play some other animation simultaneously while these queues are looping, either randomly or because of user interaction. For example, look left or right.

How on earth do I achieve this?

Have you seen AnimationState? You can apply multiple animations at the same time. You can set a listener on the TrackEntry you get back from SetAnimation and use this to have a random amount of time before the next animation is played via AddAnimation.

OK - well I thought I understood how to set it up, but I'm still missing something. I have a helper method that sets up the queue with animations with random delays between them. I then have a listener on the last track entry to find out when all of the animations have finished playing and then I restart them after clearing out the tracks:

  public static void PlayAnimationQueue (string[] animationNames, float randomDelayMax, SkeletonAnimation skeletonAnimation, bool loop = false, bool separateTracks = false) {
    int track = 0;
    TrackEntry lastTrackEntry = null;
  
foreach (string animationName in animationNames) { lastTrackEntry = skeletonAnimation.state.AddAnimation (separateTracks ? track++ : 0, animationName, false, Random.Range (0, randomDelayMax)); lastTrackEntry.Complete += (Spine.AnimationState state, int trackIndex, int loopCount) => { Debug.Log ("State = " + state + " Track = " + track); }; } if (loop && lastTrackEntry != null) { lastTrackEntry.Complete += (Spine.AnimationState state, int trackIndex, int loopCount) => { skeletonAnimation.state.ClearTracks (); PlayAnimationQueue (animationNames, randomDelayMax, skeletonAnimation, loop, separateTracks); }; } }

This is used like this (I set an initial animation first):

    characterFaceAnimation.state.SetAnimation (0, "blinking", false);
    SpineCharacters.PlayAnimationQueue (new string[] {
      "eye move right",
      "idle3",
      "idle2",
      "smile",
      "blinking"
    }, 5f, characterFaceAnimation, true);

This seems to work the first time, but then the second time through after clearing tracks and adding animations again, the animations seem to be out of order and playing on top of each other.
Is there something more I need to do than clear tracks to remove the previous animations? Or is there some way of looping back to the start of the first list of animations instead of recreating the list each time?

Could be a problem with calling ClearTracks from the Complete callback, since it is called within a loop in the AnimationState. Maybe we need to queue the callbacks so they happens outside the loop. Can you verify?