- Edited
Event is fired twice in code (once in animation)
I have a callback listening to events. I have verified that each event only appears once.
However each event is fired twice (at the same time). I only call 1 animation and on one spine object and there is only one reference (so there arent two units firing events, or two listeners to one event).
The code is relatively simple:
// Event Listener
_skeletonAnimation.AnimationState.Event += (TrackEntry, Event) =>
{
if (animationEventCallback != null)
{
animationEventCallback(Event.Data.Name, unitState); // Called twice for every event
}
};
// The animation invoke
animationEventCallback = (eventName, unit) => { Debug.Log(eventName) };
_animationState.SetAnimation(0, "animationWithOneEventThatsCalledTwice", loop);
Every single event is called twice at the same time even though it only appears once in the timeline in Spine2D.
I did a time printout with each event and I get a log like this
[Log] Time passed is 0.0204173 for grrblReaction
[Log] Time passed is 0.0204173 for grrblReaction
[Log] Time passed is 0.0204173 for monsterReaction
[Log] Time passed is 0.0204173 for monsterReaction
[Log] Time passed is 0.0755396 for moveGrrblForward
[Log] Time passed is 0.0755396 for moveGrrblForward
[Log] Time passed is 2.10146 for cameraShake
[Log] Time passed is 2.10146 for cameraShake
[Log] Time passed is 2.10146 for monsterKnockback
[Log] Time passed is 2.10146 for monsterKnockback
[Log] Time passed is 2.10146 for tweenMonsterRed
[Log] Time passed is 2.10146 for tweenMonsterRed
[Log] Time passed is 2.305758 for tweenMonsterWhite
[Log] Time passed is 2.305758 for tweenMonsterWhite
[Log] Time passed is 2.500231 for tweenMonsterNormal
[Log] Time passed is 2.500231 for tweenMonsterNormal
[Log] Time passed is 2.567319 for moveGrrblBack
[Log] Time passed is 2.567319 for moveGrrblBack
Can you think of a reason my events are firing twice with only one reference?
Here is a screen shot of the spine file with each event being dispatched once:
AnimationState update
advances the time for the animation(s) and updates the state. AnimationState apply
applies the current state to a skeleton. This doesn't have side effects and doesn't change the state, which allows you to apply it to multiple skeletons before advancing the state with AnimationState update
.
Maybe you are calling AnimationState apply
twice without calling AnimationState update
between them? That would give the behavior you describe.
@Aggressor Please note that when using spine-unity, you should not call Update
or Apply
manually and let the SkeletonAnimation
component do it automatically.
You could check your above code in complete isolation in a new Unity project with just your problematic asset present. If this still occurs, you can send us this minimal Unity project as a zip package to contact@esotericsoftware.com.
You're welcome. You might want to check if you have perhaps also registered at the trackEntry.Event
returned from SetAnimation()
in addition to registering at AnimationState.Event
. While I don't see it in your posted code, perhaps you have removed it for the sake of simplicity.
The issue is this:
_skeletonAnimation.AnimationState.Event += (TrackEntry, Event) =>
{
if (animationEventCallback != null)
{
animationEventCallback(Event.Data.Name, unitState);
}
};
This is called during an init method. So this kept adding callbacks to the list so one invocation would call multiple callbacks.
I was looking around for a clean way to clean this list (without maintaining a reference manually) and there doesn't seem to be a simple solution like Event.clearAll().
Is there a way you can recommend to clear this Event list?
Aggressor wroteThis is called during an init method. So this kept adding callbacks to the list so one invocation would call multiple callbacks.
Glad to hear you've figured it out.
Aggressor wroteI was looking around for a clean way to clean this list (without maintaining a reference manually) and there doesn't seem to be a simple solution like Event.clearAll().
Is there a way you can recommend to clear this Event list?
Typically you don't want to clear an event listener list you are registering to (this would then only support a single listener), instead you want to ensure your callback method is only registered once (if you want it to be registered only once). This is basically a C# language question, as usual there are multiple ways to achieve what you want.
Using -=
before +=
is a typical solution to this problem, which first removes the event handler if it was already registered before adding it. You can see it here:
https://stackoverflow.com/questions/399648/preventing-same-event-handler-assignment-multiple-times/399772#399772
Yes I was hoping there was a simple solution without having to maintain a reference and use the +/- approach and the examples I saw without it were not ideal.
Either way, I appreciate the help, thank you very much.
You could add your listener to a TrackEntry (one specific animation) rather than the AnimationState (all animations).