← ClaudeAtlas

gameplay-architecturelisted

设计游戏玩法代码结构时使用。状态机、解耦、避免 God object。
Wade-DevCode/awesome-coding-skills-cn · ★ 3 · AI & Automation · score 78
Install: claude install-skill Wade-DevCode/awesome-coding-skills-cn
# 玩法架构 ## 何时用 - 设计角色控制器、AI 行为、UI 流程等有明显状态切换的系统时。 - 两个系统开始互相引用、代码耦合越来越重时。 - 数值、配置需要被策划频繁调整时。 - 发现 GameManager/Player 脚本越来越大、什么都往里塞时。 - 讨论是用继承还是组件/ECS 实现某个能力时。 ## 核心规则 ### 1. 状态机:显式状态,不堆标志位 **规则:** 有明确状态切换的对象(角色、UI 流程、关卡进程),用状态机建模;不用多个 bool 标志位组合表示状态;状态转移逻辑集中在一处,而不是散在各处的 if-else。 **为什么——真实会犯的错:** 角色脚本里堆了 `isAttacking`、`isRolling`、`isStunned`、`isDead`、`isInvincible` 五个 bool,处理「受击」时需要判断 `if (!isDead && !isInvincible && !isRolling)`,忘记加 `!isAttacking`,结果攻击时被打也会触发受伤动画。类似的 bug 在每次加新状态时都会出现,因为没有一个地方能看到「所有状态的完整列表」以及「哪些状态之间互斥」。 **怎么做:** - 定义枚举 `EPlayerState { Idle, Run, Attack, Roll, Stunned, Dead }`,同一时刻只有一个值。 - 状态转移写成 `TransitionTo(EPlayerState next)` 函数,内含前置条件检查,不在外部随意改状态。 - 每个状态的 Enter/Update/Exit 逻辑用子类或字典组织,不堆在同一个 Update 方法里。 - 复杂 AI 考虑分层状态机(HSM)或行为树,但先从平坦状态机起步,确实需要再升级。 --- ### 2. 事件解耦:系统间消息通信,不硬引用 **规则:** 不同系统(战斗、背包、UI、音效、成就)之间通过事件/消息总线通信;不直接持有对方的引用;增删系统不改调用方。 **为什么——真实会犯的错:** `CombatSystem` 里直接写 `UIManager.Instance.UpdateHPBar(hp)`、`AchievementSystem.Instance.CheckKillCount()`、`AudioManager.Instance.PlayHitSound()`,战斗系统变成了蜘蛛网的中心节点,牵一发动全身。后来要给死亡加一个「慢动作特效」,需要改 CombatSystem,但 CombatSystem 的开发者对 PostProcessManager 完全不了解,加了一行代码引入了空引用崩溃。 **怎么做:** - 用全局事件总线:`EventBus.Emit("player_died", data)`,各系统独立订阅,互不知晓对方存在。 - Unity:UnityEvent、ScriptableObject 事件通道;Unreal:Gameplay Ability System 的 Tag 系统或 Delegate;Godot:Autoload 中的 signal 总线。 - 订阅时注意生命周期:系统销毁时取消订阅,防止向已销毁对象发送消息。 - 不是所有通信都要用事件——父子组件之间直接调用方法完全正常,事件总线是**跨系统**通信的工具。 --- ### 3. 数据驱动:配置走数据,不写死代码 **规则:** 角色属性、技能数值、掉落概率、关卡参数等所