cocos-creator-tween-animlisted
Install: claude install-skill Wade-DevCode/awesome-coding-skills-cn
# Cocos Creator 动画与缓动
## 何时用
- 用 `tween` 做 UI 弹出、飞金币、按钮点击反馈等动效时。
- 使用 `Animation` 组件播放帧动画,或在动画结束时触发游戏逻辑时。
- 集成 Spine 骨骼动画,遇到性能问题或换装需求时。
- 节点销毁后控制台仍然报错(回调访问已销毁节点、tween 继续运行)时。
- 动效卡顿、帧率与期望不符,或动画在不同帧率设备上速度不一致时。
## 核心规则
### 1. tween 用法:链式 API 做 UI 动效,销毁前必须 stopAllByTarget
**规则:** UI 动效优先用 `tween(node).to(...).call(...).start()` 链式写法;节点销毁、场景切换、或主动取消动效时,必须调用 `Tween.stopAllByTarget(node)` 停止该节点上所有正在运行的 tween;不要把 tween 的 `.call()` 回调里对节点的访问放在延迟后,而不先判断节点有效性。
**为什么:** 这是 Creator 项目里最高频的运行时报错来源之一。典型场景:UI 弹窗弹出动画还没播完(0.3s tween),玩家点了关闭按钮,弹窗节点被 `destroy`,0.3s 后 tween 的 `.call()` 回调执行——此时 `this` 或捕获的节点引用已销毁,访问任何属性都抛出 `Cannot read properties of null`,且错误栈指向 tween 引擎内部,极难定位。另一个常见错误:节点池归还时没有停止节点上的 tween,下次取出时旧 tween 仍在运行,与新 tween 叠加,节点产生错乱的双重动画。
**怎么做:**
- 启动:`tween(this.node).to(0.3, { scale: new Vec3(1,1,1) }, { easing: 'backOut' }).call(() => { this.onShowComplete(); }).start();`
- 节点销毁时:`onDestroy() { Tween.stopAllByTarget(this.node); }`
- 节点池归还时(`unuse`):`Tween.stopAllByTarget(this.node);`
- 回调内访问组件:先判断 `if (!this.isValid) return;`,防止节点已销毁后回调被延迟触发。
- 需要保留 tween 引用以便手动取消:`this._showTween = tween(node).to(...).start();`,取消时 `this._showTween?.stop();`。
---
### 2. Animation 组件:帧/骨骼动画播放,关键时机用帧事件而非硬编码计时
**规则:** 帧动画和骨骼动画的时机逻辑(播放完毕后跳转状态、攻击动画命中帧触发伤害)用 Animation 的帧事件(`AnimationEvent`)或 `finished` 事件回调触发,不用 `scheduleOnce(callback, duration)` 硬编码时长。
**为什么:** `scheduleOnce(this.onAttackHit, 0.35)` 是新手最常写的"动画同步"方案。问题一:动画时长一旦被美术调整(0.35s 改 0.4s),程序代码里的数字忘了改,命中判定就永远提前或延后。问题二:设备帧率波动导致动画实际播放时长和计