Animation sequencing

Hey everybody, hope all is well.

On a spur of the moment type of thing, I created a way to play a series of animations after some delays. I took inspiration from mostly things Sam and the team did in the last rpg course.

namespace Game.Animations
{
    public class AnimationDataUser
    {
        Animator animator;

        public AnimationDataUser(Animator animator)
        {
            this.animator = animator;
        }

        public Animator GetAnimatorUser()
        {
            return animator;
        }

        public void StartCoroutine(IEnumerator coroutine)
        {
            animator.GetComponent<MonoBehaviour>().StartCoroutine(coroutine);
        }
    }
}

– Afterwards I then created an abstract scriptable object class

namespace Game.Animations
{
    public abstract class AnimationInitializer : ScriptableObject
    {
        public abstract void StartAnimation(AnimationDataUser data, Action finished);
    }
}

– Then I created a class derived from AnimationInitializer where it handles the logic to playing a series of animations with boolean values and float delays so I could have it pretty design friendly. The only thing I needed to ensure was that the “Names” of the strings which in my case is actually an enum matches to that of the parameter strings inside the animator.

namespace Game.Animations
{
    [CreateAssetMenu(fileName = "Animation 0", menuName = "Scriptable Objects/Animation/Create New Animation Sequence", order = 0)]
    public class AnimationSequencing : AnimationInitializer
    {
        [SerializeField] List<AnimatorValues> animatorValues = new List<AnimatorValues>();

        [Serializable]
        public class AnimatorValues
        {
            public List<EAnimationNames> animNames = new List<EAnimationNames>();
            public List<bool> animValues = new List<bool>();
            public List<float> animationRuntime = new List<float>();
        }

        public override void StartAnimation(AnimationDataUser data, Action finished)
        {
            data.StartCoroutine(ExecuteAnimationSequence(data, finished));
        }

        public IEnumerator ExecuteAnimationSequence(AnimationDataUser data, Action finished)
        {
            foreach (AnimatorValues value in animatorValues)
            {
                for (int i = 0; i < value.animNames.Count; i++)
                {
                    data.GetAnimatorUser().SetBool(value.animNames[i].ToString(), value.animValues[i]);
                    Debug.Log(value.animNames[i] + " animation started!");
                    yield return new WaitForSeconds(value.animationRuntime[i]);
                }
            }
            finished();
        }
    }
}

– I only needed to check for the value.animNames.Count because there’s no need to have an excess amount of float or bool values, they should equal the same number to the names presented in each animatorValue collection.

And about the enum it just uses the exact same strings from my parameters but using an enum makes it a lot more readable and also saves a lot of headaches of potentially misspelling.

namespace Game.Animations
{
    public enum EAnimationNames
    {
        Idle,
        Walking,
        Attack,
        Hurt,
        Dead
        // More to add.
    }
}

– Then I made a dummy script and just called it AnimatorStore and threw it on the player, and configured up some random things

namespace Game.Animations
{
    public class AnimatorStore : MonoBehaviour
    {
        [SerializeField] AnimationInitializer animationInitializer;

        IEnumerator Start()
        {
            yield return new WaitForSeconds(3f);
            AnimationDataUser data = new AnimationDataUser(GetComponent<Animator>());
            animationInitializer.StartAnimation(data, () => AnimFinished());
        }

        void AnimFinished()
        {
            Debug.Log("Do things like end the turn after completing the final animation sequence.");
        }
    }
}

animatorsequencer
Here is a look at a set up I did for my player.

I guess the only thing left for me to figure out is how to create multiple of these animation initializer and play the correct one when i use actions. Right now AnimationStore is just looking for a single reference and it plays it on start just to test how it works – but later on I’m thinking to store every action and attack animation there and then filter through them until it finds the appropriate one to play. (Could be performance heavy no idea)

Any feedback is much appreciated

1 Like

Privacy & Terms