Enemies spawn with multiple of the same animation events

Hey all,

I am having issues with spawning enemies and their related “attack” animation events. The more enemies I have spawn in, the more animation events get added to their attack animation.

I add the animation event to their attack on Start(). Then I instantiate my enemy characters. If I change the spawn values to spawn 1 enemy everything works out well. If I spawn multiple enemies, that number corresponds to the number of animation events that get added. So as you progress in the game enemies get much harder as they exponentially do more damage. This is not what I want. I tried changing where I added the animation event. I tried adding it once a character was spawned but no luck.

Here is my animation event Function code:

function addAnimEvent( t_eventTime : float, animName : String, funcName : String, eTrans : Transform, takeDam : float)
{
	var aEvent : AnimationEvent = new AnimationEvent(); //create animation event
	aEvent.time = t_eventTime; // add a time value to the animation event
	//aEvent.messageOptions = SendMessageOptions.DontRequireReceiver;
	aEvent.functionName = funcName; // add the function to call from the animation event
	aEvent.floatParameter = takeDam;
	if(animName != null)
	{
		var aState : AnimationState; //create variable to hold my animation state
		aState = eTrans.animation[animName]; //find the correct anim name to add the animation event to
		aState.clip.AddEvent(aEvent); // add the animation event to the animation clip
	}
}

Here is my spawn code:

function spawnEnemy()
{

	if(spawn == true)
	{	
		while(enemyCnt <= enemy1cnt && spawnPoints != null && isDead != true)
		{
			spawn = false;
			var i : int = Random.Range(0,spawnPoints.length);
			Instantiate(enemy1, spawnPoints_.transform.position, spawnPoints*.transform.rotation);*_

* enemyCnt++;*
* yield new WaitForSeconds(enemy1Off);*
* }*
* spawn = true;*
* }*
}
Any help would be greatly appreciated. I’m an animator by trade so please forgive my coding skills :slight_smile:
Thanks in advance!
Alex

aState.clip.AddEvent(aEvent);

You’re adding event to AnimationClip. AnimtionClips are shared between animation states and your characters, so every time you add an event it gets added to the same clip. Just add events when you spawn first enemy, and do not add events when spawning other enemies.

This is so wrong… Unity should fix it. Animators should only call the object they are attached to. I wrote my own animation event handler (AnimationTrigger) and it works very well… Don’t know why Unity couldn’t make it like this… Just attach this class to the gameObject with the Animator and add eventlisteners to the component like this

animation_trigger = gameObject.GetComponent<AnimationTrigger>();
animation_trigger.addListener(animationTriggerEvent);

and make a function

public void animationTriggerEvent(AnimationTriggerEvent e)
        {
            if (e.type == AnimationTriggerEvent.ANIMATION_EVENT)
            {
                //Debug.Log("Humanoid: ANIMATION TRIGGER");  
            } 
            animation_trigger.stopListening();
        }

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace MarchingCubesProject
{
    public class AnimationTriggerEvent {
        public static readonly int ANIMATION_EVENT = 10;
        public static readonly int ANIMATION_EVENT_ERROR = 20;

        public int type { get; set; } = 10;

        public AnimationEvent animation_event { get; set; }
    }


    /* Class to curcumvent the Unity AnimationEvent system where events are sent to all objects with that Animator
     * 
     * When startListening() is called. Update looks for events in Animator.GetCurrentAnimatorClipInfo and sends an AnimationTriggerEvent when 
     * Animator.GetCurrentAnimatorStateInfo.normalizedTime*Length > AnimationEvent.time
     * 
     * IMPORTANT - AnimationTrigger must be turned on and off with startListening() and stopListening()
     */
    public class AnimationTrigger: MonoBehaviour
    {
        public delegate void animationTriggerCallback(AnimationTriggerEvent e);

        private List<animationTriggerCallback> listeners;
        private Animator anim;                                      // Animator component
        private bool is_listening;

        // Private variables initialized when event is found 
        private AnimationEvent detected_event;
        private AnimationClip detected_clip;
        private bool wait_for_event = false; // true when event has been found and counting down to event
        private float event_time_offset = 0;

        private void Awake()
        {
            listeners = new List<animationTriggerCallback>();
        }

        private void Start()
        {
            anim = GetComponent<Animator>();
        }

        public void addListener(animationTriggerCallback listener)
        {
            listeners.Add(listener);
        }

        public void startListening()
        {
            is_listening = true;
        }

        public void stopListening()
        {
            is_listening = false;
        }

        private void callListeners(AnimationTriggerEvent e)
        {
            for (int i = 0, il = listeners.Count; i < il; i++)
            {
                listeners*(e);*

}
}

// Update is called once per frame
void Update()
{
// When Event is found and waiting till event_time_offset > detected_event.time
if (wait_for_event)
{
if (detected_event == null)
{
wait_for_event = false;
callListeners(new AnimationTriggerEvent() { type = AnimationTriggerEvent.ANIMATION_EVENT_ERROR });
}
else
{
event_time_offset += Time.deltaTime;
if (event_time_offset > detected_event.time)
{
callListeners(new AnimationTriggerEvent() { animation_event = detected_event });
wait_for_event = false;
//is_listening = false;
}
}

}

// When is_listening, looking for events in Animator.GetCurrentAnimatorClipInfo
if (is_listening && !wait_for_event)
{
if (anim != null)
{
AnimatorClipInfo[] infos = anim.GetCurrentAnimatorClipInfo(0);
for (int i = 0, il = anim.GetCurrentAnimatorClipInfoCount(0); i < il; i++)
{
AnimatorClipInfo info = infos*;*
AnimationClip clip = info.clip;
AnimationEvent[] events = clip.events;

if (events != null)
{
if (events.Length > 0)
{
AnimationEvent e = events[0];
if (e != null)
{
AnimatorStateInfo state_info = anim.GetCurrentAnimatorStateInfo(0);
event_time_offset = (state_info.normalizedTime * state_info.length);
detected_event = e;
detected_clip = clip;
wait_for_event = true;
}
}
}
}
}
}

}

}
}