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

本文记录了在Cocos Creator中使用Spine动画制作过程中遇到的问题。涉及循环播放stand动作、在特定时刻切换到attack动作并恢复的过程。在尝试监听attack动作结束时,发现官方API不完全支持,最终通过监听所有动画结束并判断动画名称来实现。解决方案利用了Promise进行外部调用控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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


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

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


阶段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的坑。

<think>好的,我现在需要回答用户关于Cocos Creator中如何通过@property装饰器获取sp.Skeleton组件的问题。首先,我需要确认用户提到的sp.Skeleton是否属于Spine动画组件。在Cocos Creator中,处理Spine动画通常使用sp.Skeleton组件,所以这部分是正确的。 接下来,用户的问题是关于在TypeScript脚本中通过@property装饰器声明属性,并指定类型为Skeleton。这里需要确认的是,是否可以直接使用{type: sp.Skeleton}来获取组件引用。根据Cocos Creator的文档,当在@property装饰器中指定type参数时,如果类型是继承自Component的类,编辑器会自动识别并允许拖拽节点或组件到属性检查器中。 但要注意的是,sp.Skeleton组件的完整路径可能需要正确导入或声明。例如,用户是否在脚本顶部正确导入了sp模块,比如使用import * as sp from 'sp.d.ts';或者类似语句。如果未正确导入,TypeScript可能会报错,导致无法识别sp.Skeleton类型。 另外,用户可能遇到的一个常见问题是在声明属性时是否正确使用了大写字母。例如,sp.skeleton和sp.Skeleton是不同的,后者是正确的类名。需要确认用户代码中的拼写是否正确。 此外,如果用户希望通过代码动态获取该组件,是否需要在组件初始化时使用getComponent(sp.Skeleton)方法。虽然@property装饰器可以方便地在编辑器中拖拽赋值,但有时在运行时动态获取更可靠,特别是当组件可能被动态添加或删除时。 还需要考虑的是Cocos Creator的版本兼容性。不同版本中spine组件的使用方式可能有细微差别,比如模块导入方式或API的变化。建议用户查阅对应版本的官方文档以确保兼容性。 总结可能的步骤:首先确认是否正确导入sp模块,其次检查@property中的类型是否正确指定为sp.Skeleton,然后在编辑器中拖拽节点或组件进行测试。如果仍有问题,检查控制台是否有TypeScript错误,并确保组件所在的节点确实附加了sp.Skeleton组件。 最后,给出一个具体的代码示例会更有帮助,展示如何正确声明和使用该属性,并说明常见的错误点,如拼写错误、未正确导入模块等。同时提醒用户如果在运行时需要获取组件,应在start或onLoad生命周期方法中使用getComponent来确保组件已就绪。</think>在Cocos Creator中,可以通过以下方式正确获取sp.Skeleton组件: ```typescript // 首先确保已导入sp模块(Cocos Creator 2.x+ 会自动声明) import { _decorator, Component, Node } from 'cc'; const { ccclass, property } = _decorator; @ccclass export class YourComponent extends Component { // 正确声明方式 @property({ type: sp.Skeleton }) public skeleton: sp.Skeleton = null!; // 或者简写形式(Cocos Creator 2.4.3+) @property(sp.Skeleton) public skeleton: sp.Skeleton = null!; } ``` 关键点说明: 1. **类型声明** ✅ - 必须使用完整的`sp.Skeleton`类型声明 - 编辑器会自动识别Spine组件类型 2. **编辑器操作** 🖱️ - 在属性检查器中可以: ➢ 拖拽带有sp.Skeleton组件的节点到属性框 ➢ 直接拖拽组件实例到属性框 3. **常见问题排查** 🔍: - ❌ 拼写错误:`sp.skeleton`(小写)无效 - ❌ 未导入模块:确保项目有`spine.d.ts`类型声明 - ❌ 节点未挂载:检查目标节点是否确实有sp.Skeleton组件 4. **运行时获取方式** ⚙️: ```typescript // 在onLoad或start生命周期中获取 private _skeleton: sp.Skeleton = null!; start() { this._skeleton = this.node.getComponent(sp.Skeleton); // 使用前建议空检查 if (this._skeleton) { this._skeleton.setAnimation(0, 'run', true); } } ``` 5. **版本注意事项** 📌: - Cocos Creator 3.x:继续沿用此方式 - Cocos Creator 2.x:需要启用引擎的spine模块 - Web平台:确保构建时包含spine模块 建议通过`@property`声明后在编辑器拖拽赋值,这样既直观又避免硬编码路径。如果组件可能动态变化,建议结合编辑器赋值和运行时`getComponent`双保险。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值