- Modifié
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 a écritThis 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 a écritI 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).