游戏拆解与组装(非 ECS)
「游戏拆解与组装」讲的是一套非 ECS 的拆解与组装案例:游戏程序拆成 Engine(支撑子系统)与 Game(业务子系统),再由 GameApplication 组装。Engine 负责「怎么运行」,Game 负责「运行什么」——这是拆解与组织原则在游戏上的完整应用,不依赖 ECS。这一条线就是这个案例本身:游戏怎么拆、怎么组。
一、先把「支撑子系统 / 业务子系统 / 调度组装」分开
一个游戏程序可以抽象成两个子系统:
1 2 3
| 游戏程序 ├── Engine 子系统 ← 支撑 └── Game 子系统 ← 业务
|
1 2 3 4 5
| Engine ├── ECS / Rendering / Physics / Input / Audio / Resource / Scene
Game ├── Player / Enemy / Weapon / Character / Inventory / Quest / GameRule
|
Engine 是支撑子系统,Game 是业务子系统。 这是游戏拆解的第一刀——把「怎么运行游戏」和「游戏内容是什么」分开。
二、Engine 继续拆(支撑子系统)
1 2 3 4 5
| Engine ├── ECS World / Entity / ComponentStorage / Query / Scheduler ├── Rendering Renderer / Mesh / Material / Camera / RenderPass ├── Physics World / RigidBody / Collider / CollisionQuery ├── Input / Audio / Resource / Scene
|
每个支撑子系统内部再拆成组件——与任何大型软件的系统拆分相同。
三、Game 也完全一样拆(业务子系统)
1 2 3 4 5
| Game ├── Character CharacterComponent / MovementSystem / CharacterController / CharacterData ├── Combat HealthComponent / AttackComponent / DamageSystem / AttackSystem / CombatRule ├── Inventory InventoryComponent / ItemComponent / InventorySystem / ItemRule ├── Quest / AI / World
|
Engine Component 和 Game Component 在「组件化」层面没有区别。 区别只是:Engine Component 支撑游戏,Game Component 实现具体游戏。
四、谁来组装:GameApplication
不是 main 一个个 new 所有东西,而是 GameApplication 负责组装:
1 2 3 4 5 6 7 8 9 10 11
| int main() { GameApplication app; app.run(); }
class GameApplication { void run() { Engine engine; Game game; game.registerComponents(engine); game.registerSystems(engine); engine.run(); } };
|
Engine 负责「怎么运行」
1 2 3 4 5 6 7 8 9 10 11
| class Engine { void run() { while (running) { input.update(); ecs.update(); physics.update(); rendering.render(); audio.update(); } } };
|
Engine 负责生命周期、运行循环、系统调度、基础设施、资源管理;它不知道游戏规则。
Game 负责「运行什么」
1 2 3 4 5 6 7 8 9 10 11
| class Game { void registerComponents(Engine& engine) { engine.ecs.registerComponent<Transform>(); engine.ecs.registerComponent<Health>(); engine.ecs.registerComponent<Weapon>(); } void registerSystems(Engine& engine) { engine.ecs.addSystem<MovementSystem>(); engine.ecs.addSystem<CombatSystem>(); } };
|
Game 不自己运行——它把「有哪些组件、有哪些系统」告诉 Engine,由 Engine 运行。
五、完整组装关系
1 2 3 4 5 6 7 8 9 10 11 12 13
| GameApplication │ ┌──────────────┴──────────────┐ ↓ ↓ Engine Game ┌─────┼─────┐ ┌────────┼────────┐ ↓ ↓ ↓ ↓ ↓ ↓ ECS Rendering Physics Character Combat Inventory │ └── Scheduler │ ↓ Game Systems(Movement / Combat / Enemy / Inventory)
|
真正运行时:
1
| GameApplication → Engine → Scheduler → Game Systems → ECS World → Game Components
|
六、不要把 Game System 和 Engine Scheduler 混为一谈
1 2
| CombatSystem → 业务(找到攻击者、计算伤害、修改 Health) Scheduler → 支撑(只知道什么时候运行 CombatSystem)
|
Scheduler 不知道「伤害是多少」,只知道「什么时候运行 CombatSystem」。
七、游戏业务也可再框架化
如果游戏很复杂,还可以继续:
1 2 3 4 5
| Engine ↓ Game Framework(RPG Framework:Character/Inventory/Quest/Combat/Save) ↓ 具体 RPG(魔法/武器/敌人/具体任务)
|
下层框架提供运行和组装能力,上层框架利用下层框架再次进行领域组装。 ECS Engine 是支撑;Game 是业务;Scheduler 是 Engine 提供的运行机制;Game Systems 是业务逻辑;GameApplication 是把 Engine 和 Game 组装起来的应用层。
八、这一条线的位置
1 2 3 4 5
| 拆解与组织(主题): 01 元原则(拆解+组织) 02 边界(在哪切) 03 游戏拆解与组装(本线:拆解与组织在游戏上的完整案例,非 ECS) 04 ECS 与注册机制(03 的基础上加入运行时可扩展 = 注册机制)
|
本线是「非 ECS」的游戏拆解组装:Engine/Game 拆开、GameApplication 组装。ECS 只是在这一基础上额外加了一个机制(注册机制,见 04),不是本线的前提。
收束
1 2 3 4 5 6 7 8 9 10 11 12 13
| 游戏拆解的第一刀: Engine(支撑子系统)vs Game(业务子系统)
Engine 负责「怎么运行」:生命周期、运行循环、系统调度 Game 负责「运行什么」:注册组件、注册系统
组装者是 GameApplication: main → app.run() → 创建 Engine/Game → 注册 → engine.run()
不要混: CombatSystem(业务)vs Scheduler(支撑)
可再框架化:Engine → Game Framework → 具体 RPG
|
游戏的拆解与组装 = 拆成 Engine 与 Game,由 GameApplication 组装。 这是拆解与组织原则的完整案例——不依赖 ECS。