fengmin Unfortunately, it is not possible to handle events in exactly the same way when using SkeletonMecanim. For information on how to handle events with SkeletonMecanim, see the "SkeletonMecanim Events" section: https://zh.esotericsoftware.com/spine-unity#SkeletonMecanim%E4%BA%8B%E4%BB%B6
使用SkeletonMecanim时spine event相关问题
- Editado
顺便我想问一下:同时注册多个事件,注册多次事件会导致unity崩溃吗
例如:
private void OnEnable()
{
Idleanimator.AnimationState.Start += JumpMethod;
Idleanimator.AnimationState.Complete += IdleAnimalComplete;
Idleanimator.AnimationState.End += IdleAnimalEnd;
Idleanimator.AnimationState.Event += CrouchPause;
attackAnimator.AnimationState.Complete += AttckAnimalComplete;
attackAnimator.AnimationState.End += AttckAnimalComplete;
attackAnimator.AnimationState.Complete += ResetEventCount;
attackAnimator.AnimationState.Event += HandleAnimationEvent;
attackAnimator.AnimationState.Start += AttackStart;
attackAnimator.AnimationState.End += ResetEventCount;
}
private void OnDisable()
{
Idleanimator.AnimationState.End -= IdleAnimalEnd;
Idleanimator.AnimationState.Complete -= IdleAnimalComplete;
attackAnimator.AnimationState.Event -= HandleAnimationEvent;
attackAnimator.AnimationState.Complete -= AttckAnimalComplete;
attackAnimator.AnimationState.Complete -= ResetEventCount;
attackAnimator.AnimationState.End -= ResetEventCount;
attackAnimator.AnimationState.End -= AttckAnimalComplete;
Idleanimator.AnimationState.Event -= CrouchPause;
Idleanimator.AnimationState.Start -= JumpMethod;
Idleanimator.AnimationState.Start -= CrouchMechod;
}
我发现:
attackAnimator.AnimationState.Complete += AttckAnimalComplete;
attackAnimator.AnimationState.End += AttckAnimalComplete;
会导致崩溃,AttckAnimalComplete函数只是负责了动画结束时设置一些状态为false;因此我希望在End和Complete都使用,但是却导致了崩溃
If you receive crashes, you're doing something wrong.
If you receive a NullReferenceException, likely in OnEnable()
your references like Idleanimator.AnimationState
are not set up yet. If you're using recent spine-unity versions, accessing skeletonAnimation.AnimationState
will initialize it automatically, while on older versions you will need to call skeletonAnimation.Initialize(false);
.
What does the crash say, or what is the exception message saying?
Noticing the lines:
Idleanimator.AnimationState.Start += JumpMethod;
..
attackAnimator.AnimationState.Complete += AttckAnimalComplete;
What is Idleanimator
and what is attackAnimator
? Are they separate SkeletonAnimation
instances? Are you sure that you want to have multiple SkeletonAnimation
objects and not a single one which plays all animations?
Note that you can also register events to a single TrackEntry
after starting or adding an animation
Spine.TrackEntry trackEntry = animationState.SetAnimation(trackIndex, "attack", true);
trackEntry.Start += OnSpineAnimationStart;
(See the documentation here or in English here)
fengmin I should have told you this earlier, but there is a translation button on the forum so you can post your reply in your native language.
It looks like you didn't answer Harald's question. Please tell us what Idleanimator
and AttackAnimator
do.
Are you trying to have multiple SkeletonAnimation
objects?
If you want to handle the events of the idle animation and the attack animation separately, as Harald suggested, it would be best to use TrackEntry
to register only the events for specific animations. Have you tried the code Harald suggested?
是的,我用来控制多个不同gameobject下的不同SkeletonAnimation对象
问题是
attackAnimator.AnimationState.Complete += AttckAnimalComplete;
attackAnimator.AnimationState.End += AttckAnimalComplete;
调用的是同一个函数AttckAnimalComplete,如果单独使用.Complete是可以正常运行的,但是End会导致unity停止响应
After trying this, Unity froze even if I just called SetEmptyAnimation()
on both the Complete
and End
events, so it seems that the problem is not ClearTracks()
, but that you are trying to do these operations on both Complete
and End
. In fact, I think there is usually no need to call this on both Complete
and End
, so why is it necessary on both? If you want to call the method when the loop is complete, register Complete, and if you want to call it when the playing animation switches to another animation or finishes playing, register End should be sufficient.
fengmin Unfortunately, I'm not sure why the crashes occur, but I think Harald will answer that later.
Anyway, I think there are some solutions. For example, you can modify the code to register a handler for the End
event of the TrackEntry and call AddEmptyAnimation()
beforehand so that the animation returns to the setup pose when it is complete.
Spine.TrackEntry trackEntry = attackAnimator.SetAnimation(0, "attack", false);
trackEntry.End += AttckAnimalComplete;
animationState.AddEmptyAnimation(0, 0, 0);
This way, the End
event is fired when the animation switches to the empty animation, so it is sufficient to simply register a method to the End
event. This allows you to cover both the case where the animation is complete, and the case where the animation is switched to another before it is complete.
fengmin Oh, sorry, I forgot to add that I assumed that the AttckAnimalComplete()
would be like this:
void AttckAnimalComplete(Spine.TrackEntry trackEntry) {
isAttk = false;
isAttked = true;
playerState.playerState = CharacterState.Idle;
attackAnimator.state.SetEmptyAnimation(0, 0);
}
Please note that ClearTracks()
does not reset the pose of the previous animation. This is explained in the API reference: https://esotericsoftware.com/spine-api-reference#AnimationState-clearTracks
So you should use SetEmptyAnimation()
instead of ClearTracks()
.
Misaki After trying this, Unity froze even if I just called SetEmptyAnimation() on both the Complete and End events, so it seems that the problem is not ClearTracks(), but that you are trying to do these operations on both Complete and End.
@fengmin Note that SetEmptyAnimation()
or SetAnimation()
in general is also triggering End
and Complete
callbacks. You're creating an infinite loop if you call SetEmptyAnimation()
or SetAnimation()
from a callback of AnimationState.End
or Complete
. You need to either register to callbacks of a single TrackEntry
like trackEntry.End += YourCallback
or use AddEmptyAnimation()
as Misaki mentioned above.
Harald 所以是因为在“attack”动画End或Complete时,SetEmptyAnimation()的这个EmptyAnimation本身也会带有End 和 Complete回调并且被瞬间执行,导致了无限循环,那么同理这里使用AddEmptyAnimation()是否也会无限循环,EmptyAnimation的名称是什么,我可以通过在开头进行非空判断来避免循环吗,例如
private void AttckAnimalComplete(TrackEntry trackEntry)
{
if(trackEntry.Animation.Name.Equals(""))
return
isAttk = false;
SetEmptyAnimation();
}