Animation Function Effect

Here is a Scriptable object I cobbled together to use an animation function in an animation clip to trigger the other effects. It uses the time the animation function is at in the animation or the animation time if there are no functions.

The handy part of this is that even if the animation function gets skipped over, it should still trigger the sub-events.

namespace RPG.Abilities.Effects
{
    [CreateAssetMenu(fileName = "Animaion Function Composite Effect", menuName = "RPG/Abilities/Effects/Animation Function Composite", order = 0)]

    public class AnimationFunctionCompositeEffect : EffectStrategy_SO
    {
        
        [SerializeField] [Tooltip("Name of the trigger to fire in the animation contoler")] 
        string animationTrigger;       
        [SerializeField] [Tooltip("Name of the animation clip in the animation contoler state")] 
        string aimationName;           
        [SerializeField] [Tooltip("Name of the functon to trigger the delayed effects")] 
        string animationFunctionName;         
        [SerializeField] [Tooltip("Layer the animation is on in the animation contoler")]
        int animationLayer = 0;

        [SerializeField] EffectStrategy_SO[] delayedEffects;
        public override void StartEffect(AbilityData data, Action finished)
        {
            data.StartCoroutine(TriggeredEffect(data, finished));
        }

        private IEnumerator TriggeredEffect(AbilityData data, Action finished)
        {
            Animator animator = data.GetUser().GetComponent<Animator>();
            animator.SetTrigger(animationTrigger);

            AnimationClip clipToWatch = FindAnimation(animator, aimationName);

            AnimationEvent[] animationEvent = clipToWatch.events;
            float delay = clipToWatch.length;
            if (animationEvent.Length <= 0)
            {
                Debug.Log("No events found");
            }
            else
            {
                for (int i = 0; i < animationEvent.Length; i++)
                {
                    if (animationEvent[i].functionName.ToString() == animationFunctionName)
                    {
                        delay = animationEvent[i].time;
                        break;
                    }
                }
            }

            yield return new WaitForSeconds(delay);

            foreach (var effect in delayedEffects)
            {
                effect.StartEffect(data, finished);
            }
        }

        public AnimationClip FindAnimation(Animator animator, string name)
        {
            foreach (AnimationClip clip in animator.runtimeAnimatorController.animationClips)
            {
                if (clip.name == name)
                {
                    return clip;
                }
            }

            return null;
        }
    }
}
2 Likes

Well done!

Wonderful done, i implemented it right away, after i understood what u had done :sweat_smile:

Privacy & Terms