
网罗开发 (小红书、快手、视频号同名)
大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。
图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验 。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。
展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索"展菲",即可纵览我在各大平台的知识足迹。
每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
文章目录
-
- 引言
- 一、动画真正解决的是什么?
- 二、动画不应该属于业务逻辑
- 三、动画系统在架构中的位置
- [四、动画状态机(Animation State Machine)](#四、动画状态机(Animation State Machine))
- 五、定义动画状态
- [六、动画状态机 Demo](#六、动画状态机 Demo)
- 七、为什么状态驱动动画更重要?
- 八、动画事件系统
- 九、技能动画系统
- 十、特效系统拆分
- [十一、UI 动画也应该系统化](#十一、UI 动画也应该系统化)
- [十二、AISystem 与动画系统协同](#十二、AISystem 与动画系统协同)
- 十三、动画性能优化
- [十四、未来架构:Animation Graph](#十四、未来架构:Animation Graph)
- 十五、一个关键认知升级
- 总结
引言
很多开发者第一次做鸿蒙游戏动画时,思路通常是这样的:
text
角色移动
↓
播放动画
角色攻击
↓
播放动画
角色死亡
↓
播放动画
于是代码慢慢变成:
ts
if (state == "idle") {
playIdle()
}
if (state == "run") {
playRun()
}
if (state == "attack") {
playAttack()
}
游戏初期没什么问题。但随着项目变大:
text
待机
跑步
攻击
受伤
死亡
技能1
技能2
技能3
Buff动画
特效动画
UI动画
你会发现:
text
动画越来越多
状态越来越乱
切换越来越复杂
最终出现经典问题:
动画和业务逻辑耦合在一起。
例如:
ts
attack() {
playAttack()
enemy.hp -= 100
}
看起来很自然。但实际上:
text
动画
业务
状态
已经混在一起了。大型游戏最终都会发现:
动画不是特效,而是一个独立系统。
一、动画真正解决的是什么?
很多人认为:
text
动画 = 好看
实际上:
text
动画 = 状态变化可视化
例如,角色攻击:
text
Store变化
↓
enemy.hp减少
玩家看不到。所以需要:
text
攻击动作
伤害飘字
受击效果
告诉玩家:
text
世界发生了变化
本质上:
动画是状态变化的翻译器。
二、动画不应该属于业务逻辑
错误写法:
ts
attackEnemy() {
playAttack()
enemy.hp -= 100
}
问题:
text
BattleSystem
依赖动画
耦合严重。
正确结构:
text
BattleSystem
↓
Store变化
↓
AnimationSystem
↓
播放动画
例如:
ts
battle.attack(store)
修改:
ts
store.enemyHp -= 100
然后:
ts
AnimationSystem
监听变化。
三、动画系统在架构中的位置
前面我们一直讲:
text
Input
↓
System
↓
Store
↓
HUD
↓
UI
动画应该插在哪里?答案:
text
Input
↓
System
↓
Store
↓
AnimationSystem
↓
HUD/UI
因为:
text
动画来自状态变化
而不是:
text
按钮点击
四、动画状态机(Animation State Machine)
大型游戏不会这样写:
ts
playIdle()
playRun()
playAttack()
而是:
text
AnimationStateMachine
管理状态,例如:
text
Idle
Run
Attack
Hit
Dead
关系:
text
Idle
↓
Run
↓
Attack
↓
Idle
形成:
text
状态机
五、定义动画状态
ts
enum AnimationState {
Idle,
Run,
Attack,
Hit,
Dead
}
角色保存:
ts
class CharacterStore {
animation =
AnimationState.Idle
}
动画状态成为:
text
Store的一部分
六、动画状态机 Demo
实现:
ts
class AnimationSystem {
update(
store: CharacterStore
) {
if (store.hp <= 0) {
store.animation =
AnimationState.Dead
return
}
}
}
作用:
text
状态决定动画
而不是:
text
动画决定状态
七、为什么状态驱动动画更重要?
错误思路:
text
攻击
↓
播放动画
↓
修改状态
容易不同步。
正确:
text
攻击
↓
修改状态
↓
动画自动切换
例如:
ts
store.isAttacking = true
动画系统读取:
ts
isAttacking
自动播放:
text
Attack Animation
八、动画事件系统
很多动画会触发:
text
攻击命中
技能爆炸
伤害计算
例如:
text
挥刀
↓
第8帧
↓
真正造成伤害
不能:
text
点击就扣血
否则:
text
动画和表现错位
推荐:
text
Animation Event
机制。
定义:
ts
class AnimationEvent {
frame: number
callback: Function
}
例如:
ts
frame = 8
触发:
ts
battle.hitEnemy()
九、技能动画系统
很多技能:
text
抬手
施法
释放
结束
并不是一个动作,例如:
text
FireBall
流程:
text
Cast
↓
Launch
↓
Impact
动画系统负责:
text
阶段切换
而:
text
BattleSystem
负责:
text
伤害计算
十、特效系统拆分
很多项目喜欢:
ts
playEffect()
到处调用,最后:
text
特效失控
推荐独立:
text
EffectSystem
结构:
text
AnimationSystem
↓
EffectSystem
例如:
text
攻击动画
触发:
text
刀光特效
动画和特效分离。
十一、UI 动画也应该系统化
例如:
text
获得金币
升级
任务完成
很多开发者直接写:
ts
.animate()
在页面里。
项目大了之后:
text
无法统一管理
推荐:
text
UIAnimationSystem
负责:
text
Toast
弹窗
奖励动画
形成:
text
GameAnimationSystem
UIAnimationSystem
双系统。
十二、AISystem 与动画系统协同
前面讲过:
text
AISystem
驱动 NPC,例如:
text
NPC决定攻击
执行:
ts
store.state = Attack
然后:
text
AnimationSystem
自动切换:
text
Attack Animation
结构:
text
AISystem
↓
Store
↓
AnimationSystem
非常清晰。
十三、动画性能优化
很多项目掉帧并不是:
text
AI
导致,而是:
text
动画太多
例如:
text
100个敌人
100个动画
同时更新。
优化方案:
text
LOD动画
即:
text
远距离
简化动画
近距离
完整动画
例如:
ts
if (distance > 500) {
skipAnimation()
}
大型游戏非常常见。
十四、未来架构:Animation Graph
再往后发展,行为树管理:
text
AI决策
状态机管理:
text
动画状态
最终演化:
text
Animation Graph
结构:
text
Idle
↓
Run
↓
Attack
↓
Skill
↓
Dead
节点可视化连接,这也是现代游戏引擎普遍采用的方案。
十五、一个关键认知升级
初学者认为:
text
动画 = 播放图片
进阶开发者认为:
text
动画 = 状态切换
而大型项目最终理解:
动画系统的本质,是把 Store 中的状态变化翻译成玩家能够感知的视觉反馈。
所以真正驱动动画的不是:
text
按钮
也不是:
text
页面
而是:
text
Store
总结
鸿蒙游戏动画系统推荐架构:
text
Input
↓
System
↓
Store
↓
AnimationSystem
↓
EffectSystem
↓
HUD/UI
核心模块:
text
AnimationStateMachine
AnimationEvent
EffectSystem
UIAnimationSystem
核心原则:
text
状态驱动动画
动画不驱动状态
如果用一句话总结:
优秀的动画系统从来不是"播放动作",而是让 Store 中的状态变化,以最自然的方式呈现在玩家眼前。