Oops Framework 转职系统实战:Cocos Creator 3.x Spine武器动画切换与属性联动完整指南
【免费下载链接】oops-framework基于 Cocos Creator 3.x 版本开发的游戏框架,此项目为 Oops Framework 教程项目,如果使用框架制作游戏项目可下载 oops-game-kit 游戏项目模板开发。项目地址: https://gitcode.com/gh_mirrors/oo/oops-framework
Oops Framework 是一个基于 Cocos Creator 3.x 开发的游戏框架,本教程项目带你实战一套完整的角色转职系统:点击按钮一键转职后,Spine 骨骼角色自动切换武器动画(刀、弓、匕首),同时力量/敏捷等战斗属性随职业数据表自动重算,业务层与视图层通过事件完全解耦。下面带你理清整条链路。
🎮 转职系统能做什么?
先看一下效果:角色身上挂着一个 Spine 骨骼动画,点击"转职"按钮后,角色立即换装持新武器,并刷新当前播放的动作(待机/攻击/受击/死亡),角色属性面板上的力量、敏捷数值也随之更新。
整个系统由四个模块协作完成:
| 模块 | 文件 | 职责 |
|---|---|---|
| 转职业务 | RoleChangeJob.ts | 接收转职指令,驱动数据更新 |
| 职业数据 | RoleModelJobComp.ts | 读取职业表,联动战斗属性 |
| 动画控制 | RoleViewAnimator.ts | Spine 武器动画名拼接与切换 |
| 视图入口 | RoleViewComp.ts | 监听转职事件,刷新动画 |
角色框架采用 ECS(实体-组件-系统)思路组织,Role.ts 中Role实体把"数据层 / 业务层 / 视图层"的组件声明得清清楚楚,这也是本框架模块化的体现:
⚙️ 一键转职:用 ECS 组件触发业务逻辑
转职的入口在 Role.ts 的changeJob(jobId)方法——它不直接做任何业务,而是往实体上add一个RoleChangeJobComp组件,把职业编号塞进去:
changeJob(jobId: number) { var rcj = this.add(RoleChangeJobComp); rcj.jobId = jobId; }这是 ECS 的精髓:组件即"输入参数"。一旦RoleChangeJobComp被添加到实体上,RoleChangeJobSystem 就立刻感知到(filter匹配到该组件),执行三步:
- 把新职业编号写入
e.RoleModelJob.id(触发属性联动,见下一节); - 通过
oops.message.dispatchEvent(RoleEvent.ChangeJob)发出转职全局事件(触发武器动画切换,见下节); e.remove(RoleChangeJobComp)移除自身,完成这一次业务的生命周期。
这种"加组件触发、完事即移除"的设计,让转职逻辑天然可复用、可组合,后续加"转职条件校验""转职特效"只需追加新的 System 即可。
🗡️ Spine 武器动画切换的核心技巧
角色动画由 RoleViewAnimator.ts 控制,它继承框架自带的AnimatorSpine动画状态机,真正"换武器"的魔法在两处:
① 武器名映射表。RoleEnum.ts 中定义了WeaponName,把职业表的武器编号翻译成动画后缀:
var WeaponName: any = { 0: "Fist", 1: "Katana", 2: "CrossGun", 5: "Arch", 9: "Wakizashi", 11: "Dagger", ... };② 动画名拼接播放。playAnimation里把"动作名 + 武器名"拼成完整 Spine 动画剪辑名(RoleViewAnimator.ts):
this.weaponAnimName = this.getWeaponAnimName(); var name = `${animName}_${this.weaponAnimName}`; // 如 Attack_Katana this._spine.setAnimation(0, name, loop);也就是说,美术只需要在 Spine 里按Idle_武器名、Attack_武器名的命名规范导出动画,代码侧就实现了任意职业任意动作的自动匹配。
关键还有一个refresh()方法(RoleViewAnimator.ts):状态机状态没变(比如正处在 Idle)时不会触发状态变化事件,所以转职后手动再触发一次onStateChange,让当前动作立刻按新武器名重播——这就是"角色转职后原地换装"的效果来源。
📊 属性联动:转职后数值自动重算
武器换完了,数值呢?RoleModelJobComp.ts 的id是一个"会做事"的 setter:
set id(value: number) { this.table.init(value); // 从 RoleJob 表加载职业数据 this._id = value; var attributes = this.ent.get(RoleModelComp).attributes; attributes.get(RoleAttributeType.power).job = this.power; // 力量 = 职业值 attributes.get(RoleAttributeType.agile).job = this.agile; // 敏捷 = 职业值 }职业数据来自导表 TableRoleJob.ts,背后是 Excel 表 RoleJob.xlsx——策划改表即可新增职业,代码零改动。
更妙的是底层数值容器 RoleNumeric.ts:每个属性被拆成Base / Job / Level / Equip / Skill等多个模块分量的求和。你只需改其中一个分量(这里是job),update()自动重算总和并回调onUpdate,界面通过 MVVM 绑定跟着刷新。职业、等级、装备互不干扰,这就是"多模块叠加值"设计的好处。
🔗 业务层与视图层:事件驱动解耦
注意 RoleChangeJobSystem 并不直接操作任何节点,它只发了一条消息。视图侧的 RoleViewComp.ts 负责监听:
this.on(RoleEvent.ChangeJob, this.onHandler, this); // 收到事件后 this.animator.refresh(); // 刷新武器动画事件枚举定义在 RoleEvent.ts。这样一来:业务层(bll)只改数据、发事件,视图层(view)只监听事件、刷表现,两层代码互不 import,删除任何一层都不影响另一层编译。这套"消息总线解耦"是 Oops Framework 贯穿始终的设计哲学。
🚀 跑起来看看:Demo 中的三个转职按钮
打开主场景,Demo.ts 里已经绑好了三个转职按钮,各自调用role.changeJob(jobId):
- 转职刀:
changeJob(1)→ 武器Katana - 转职弓:
changeJob(5)→ 武器Arch - 转职胁差:
changeJob(9)→ 武器Wakizashi
点击后依次观察:角色动画后缀变化 → 力量/敏捷数值跳变 → 属性面板自动刷新,整条链路就完整走通了。
📂 核心模块路径速查
| 说明 | 路径 |
|---|---|
| 转职业务组件/系统 | assets/script/game/role/bll/RoleChangeJob.ts |
| 职业数据组件 | assets/script/game/role/model/RoleModelJobComp.ts |
| 武器名/动作名枚举 | assets/script/game/role/model/RoleEnum.ts |
| Spine 动画控制 | assets/script/game/role/view/RoleViewAnimator.ts |
| 属性多模块叠加 | assets/script/game/role/model/attribute/RoleNumeric.ts |
| 职业数据表(Excel) | excel/RoleJob.xlsx |
| 官方使用文档 | doc/using.md |
✅ 小结
- ECS 组件触发业务:
add一个RoleChangeJobComp即完成转职,System 感知后自动处理并移除组件; - Spine 动画命名规范:
动作名_武器名拼接,一份代码适配 17 种武器动画; - 属性自动联动:
RoleNumeric多模块求和 + MVVM 绑定,改职业表即可扩职业; - 事件解耦:
oops.message消息总线让业务与视图互不依赖。
想亲手把玩?可以拉取本教程项目(git clone https://gitcode.com/gh_mirrors/oo/oops-framework),用 Cocos Creator 3.x 打开即可运行。若你要用它做正式项目,框架方还提供了 oops-game-kit 游戏项目模板,本教程项目正是理解它设计思想的绝佳起点。
【免费下载链接】oops-framework基于 Cocos Creator 3.x 版本开发的游戏框架,此项目为 Oops Framework 教程项目,如果使用框架制作游戏项目可下载 oops-game-kit 游戏项目模板开发。项目地址: https://gitcode.com/gh_mirrors/oo/oops-framework
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考