[Cocos Creator] 踩坑日记(二)-连续更改Skeleton动作问题

时间:2024-04-08 19:28:38

背景:cocos creator里使用spine动画制作,关于一个spine素材有着6个(2个及以上即可)动画:

[attack, die, hit, skill, stand, walk]

[Cocos Creator] 踩坑日记(二)-连续更改Skeleton动作问题

需求:循环做着默认stand动作,在某个时刻执行动作attack,攻击结束后恢复站立动作

我们将这三个动作分为三个阶段,默认stand=>attack=>stand

[Cocos Creator] 踩坑日记(二)-连续更改Skeleton动作问题

阶段1: 设置循环stand

this.actorSkeleton.setAnimation(ActorState.STAND, 'stand', true);

阶段2: 设置单次attack

this.actorSkeleton.setAnimation(ActorState.ATTACK, 'attack', false);


通过setAnimation方法我们能简单的实现1,2两步。

阶段3:监听attack动作结束,设置动作回到stand

根据官方API,setAnimation会返回一个tracyEntry的对象,如何监听这个tracyEntry对象?答案是并没有完全支持:


  • setTrackStartListener 用来为指定的 TrackEntry 设置动画开始播放的事件监听。(只支持 Web 平台)
  • setTrackInterruptListener 用来为指定的 TrackEntry 设置动画被打断的事件监听。(只支持 Web 平台)
  • setTrackEndListener 用来为指定的 TrackEntry 设置动画播放结束的事件监听。(只支持 Web 平台)
  • setTrackDisposeListener 用来为指定的 TrackEntry 设置动画即将被销毁的事件监听。(只支持 Web 平台)
  • setTrackCompleteListener 用来为指定的 TrackEntry 设置动画一次循环播放结束的事件监听。(只支持 Web 平台)
  • setTrackEventListener 用来为指定的 TrackEntry 设置动画帧事件的监听。(只支持 Web 平台)

尝试过setTrackEndListener 、setTrackCompleteListener这两个方法,由于平台限制,均没有实际意义

无奈只好用setEndListener 用来设置动画播放完后的事件监听,这样会监听到所有动画结束,然后根据动画名来实现回调:

addActionListener(){
    this.actorSkeleton.setCompleteListener((trackEntry)=>{
    //根据动画名执行callback
    let actionName = trackEntry['animation']['name'];
    let resolve = this.resovles[actionName];
    resolve && resolve();
})
singleAnimationPromise(action, nextAction = null){
    return new Promise((resolve, reject)=>{
        let trackEntry = this.actorSkeleton.setAnimation(ActorState[action], action, false);
        if(!trackEntry){
            resolve('actor do not have the action');
        }else{
            let callBack = ()=>{
                cc.log('actor did the action', action);
                resolve('done');
                //监听一次结束,从监听序列删除
                this.resovles[action] = null;
                this.setAnimationState(nextAction || ActorState.STAND);
            }
            //这里将callback加入监听序列
            this.resovles[action] = callBack;
        }
    })
}


最后的实现里使用了promise,方便外部调用单次动作。

下一篇将会踩入到一个promise的坑。