13 KiB
13 KiB
01 · 系统架构总览
所属文档集 ← 返回索引
摘要:定义游戏的核心设计哲学、系统全景图、模块边界与系统间通信规范。
目录
1. 设计哲学
1.1 四大核心原则
| 原则 | 含义 | 实践方式 |
|---|---|---|
| 零耦合 | 系统间不持有彼此的直接引用 | 通过事件频道或统一接口通信 |
| 数据驱动 | 行为由配置数据决定,而非硬编码 | 参数外置为可配置数据模型 |
| 行为契约 | 系统对外只暴露接口,不暴露实现 | 所有跨系统调用通过接口进行 |
| 单一职责 | 每个系统只负责一件事 | 系统边界清晰,不兼管相邻职责 |
1.2 设计动词
理解游戏整体架构的关键词汇:
- 探索:玩家自由穿越相互连接的房间,逐渐解锁新区域
- 弹反:高风险高回报的格挡反击,是核心战斗循环的差异化机制
- 形态切换:三种形态提供不同战斗风格,玩家选择适合当前情况的形态
- 资源循环:灵力(攻击积累)→ 技能消耗 → 再攻击积累,形成持续循环
2. 系统全景图
┌─────────────────────────────────────────────────────────────────────┐
│ 输入层(Input Layer) │
│ 处理原始输入 → 转化为游戏动作事件 → 缓冲管理 │
└──────────────────────────────┬──────────────────────────────────────┘
│ 输入动作事件
┌──────────────────────────────▼──────────────────────────────────────┐
│ 玩家层(Player Layer) │
│ ┌──────────────┐ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ │
│ │ 移动系统 │ │ 战斗系统 │ │ 形态系统 │ │ 资源系统 │ │
│ │(Movement) │ │ (Combat) │ │ (Form) │ │(Resource)│ │
│ └──────────────┘ └─────────────┘ └─────────────┘ └──────────┘ │
└──────────────────────────────┬──────────────────────────────────────┘
│ 玩家状态事件
┌──────────────────────────────▼──────────────────────────────────────┐
│ 世界层(World Layer) │
│ ┌──────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 敌人系统 │ │ 世界系统 │ │ 进程系统 │ │
│ │ (Enemy) │ │ (World) │ │(Progression)│ │
│ └──────────────┘ └─────────────┘ └─────────────┘ │
└──────────────────────────────┬──────────────────────────────────────┘
│ 世界状态事件
┌──────────────────────────────▼──────────────────────────────────────┐
│ 支撑层(Support Layer) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ UI 系统 │ │ 音频系统 │ │ 存档系统 │ │ 叙事系统 │ │
│ │ (UI) │ │ (Audio) │ │ (Save) │ │(Narrative│ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ │
│ │ 经济系统 │ │ 反馈系统 │ │
│ │(Economy) │ │(Feedback)│ │
│ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────────┘
3. 系统分层模型
层级定义
| 层级 | 名称 | 职责 | 依赖方向 |
|---|---|---|---|
| L0 | 配置层 | 只读的设计数据(参数表、模板) | 被所有层引用,不依赖任何层 |
| L1 | 输入层 | 原始输入 → 标准化动作事件 | 依赖 L0 |
| L2 | 玩家层 | 玩家实体的所有行为 | 依赖 L0, L1 |
| L3 | 世界层 | 敌人、关卡、进程 | 依赖 L0, L2(通过接口) |
| L4 | 支撑层 | UI、音频、存档、叙事 | 订阅 L2, L3 的事件 |
设计决策:高层系统(L4)只通过事件订阅低层系统(L2、L3),不直接调用。
原因:UI 系统永远不应"告诉"玩家系统去做什么,只需观察状态变化后更新显示。
4. 通信模式规范
系统间通信允许三种方式,按优先级排序:
4.1 事件频道(优先使用)
发出方 接收方
──────── ────────
系统 A 系统 B
└─ 发出 Event<Payload> └─ 订阅 Event<Payload>
└─ 执行响应逻辑
规则:
- 发出方不知道谁在监听
- 接收方不知道谁发出了事件
- 事件只传递"发生了什么",不传递"如何处理"的指令
- 单次事件(One-shot),不轮询
4.2 接口调用(功能依赖)
调用方 被调用方
──────── ────────
系统 A 实现了 IInterface 的系统 B
└─ 持有 IInterface 引用 └─ 提供 IInterface 实现
└─ 调用 IInterface.Method()
规则:
- 调用方只知道接口,不知道实现
- 接口定义在公共层,不属于任何具体系统
- 允许同步调用并获取返回值
4.3 共享数据读取(只读访问)
消费方 数据源
──────── ────────
系统 A 配置数据 / 运行时状态数据
└─ 只读访问共享数据 └─ 数据由其所有者系统维护
规则:
- 消费方只读,不写
- 写入权唯一归属于数据的所有系统
- 其他系统通过事件订阅感知数据变化,不轮询
4.4 禁止的通信方式
| 禁止模式 | 原因 |
|---|---|
| 系统 A 直接持有系统 B 的具体引用 | 产生双向耦合,修改 B 影响 A |
| 系统 A 轮询系统 B 的状态 | 性能浪费,职责不清 |
| 事件携带"命令"语义("去做 X") | 事件只通知,不指令 |
| 支撑层系统调用玩家/世界层方法 | 违反依赖方向,UI 不应控制游戏逻辑 |
5. 数据层与逻辑层分离
5.1 两类数据
| 类型 | 说明 | 生命周期 | 示例 |
|---|---|---|---|
| 配置数据(Config) | 设计时填写,运行时只读 | 常驻内存 | 移动速度、伤害倍率、关卡布局 |
| 运行时状态(State) | 运行时动态变化 | 随场景/游戏生命周期 | 当前 HP、已解锁能力、世界标志位 |
5.2 配置数据模型的设计原则
ConfigData 特征:
✅ 字段全部只读
✅ 可被多个系统引用(共享)
✅ 可在运行前被工具验证合理性
✅ 变更不需要修改代码,只修改数据
❌ 不包含运行时可变字段
❌ 不包含对具体系统的引用
5.3 运行时状态的所有权
每份运行时状态只有一个系统拥有写权限:
| 状态 | 所有系统 | 其他系统访问方式 |
|---|---|---|
| 玩家 HP | 玩家系统 | 事件订阅 OnHPChanged |
| 世界标志位 | 叙事系统 / 世界系统 | 只读接口查询 |
| 背包道具 | 进程系统 | 只读接口查询 |
| 货币余额 | 经济系统 | 事件订阅 OnGeoChanged |
6. 模块边界原则
6.1 边界定义规则
系统的边界由以下三要素确定:
- 输入:系统响应的事件 + 调用的接口
- 输出:系统发出的事件 + 对外提供的接口
- 状态:系统独占写权限的运行时数据
6.2 系统边界一览
| 系统 | 输入来源 | 输出目标 | 独占状态 |
|---|---|---|---|
| 输入系统 | 设备原始信号 | 动作事件(发出) | — |
| 玩家系统 | 输入动作事件 | 玩家状态事件 | HP、灵力、魄元、灵泉、Geo、能力 |
| 战斗系统 | 碰撞检测结果 | 伤害事件、命中事件 | — |
| 敌人系统 | 玩家位置(只读) | 敌人行动事件 | 敌人 HP、AI 状态 |
| 世界系统 | 玩家位置(只读) | 场景切换事件 | 房间发现状态、存档点激活状态 |
| 进程系统 | 玩家动作事件 | 解锁事件 | 已解锁能力、完成度 |
| 存档系统 | 存档/读档请求 | — | 持久化数据快照 |
| UI 系统 | 全部状态事件(订阅) | 输入事件(菜单操作) | UI 层堆叠状态 |
| 音频系统 | 全部状态事件(订阅) | — | 当前音乐状态 |
| 经济系统 | 购买/掉落事件 | 货币变化事件 | Geo 余额 |
| 叙事系统 | 世界/玩家事件 | 对话事件、结局评估 | 世界标志位 |
7. 系统优先级与生命周期
7.1 启动顺序
系统初始化应遵循依赖顺序,低层先于高层初始化:
1. 存档系统(读取持久化数据)
2. 配置数据加载(所有 Config 可用)
3. 输入系统
4. 玩家系统(使用配置和存档数据初始化)
5. 世界系统(加载场景数据)
6. 敌人系统(使用世界数据初始化)
7. 支撑层系统(UI、音频、叙事等)
7.2 关卡切换时的系统行为
| 事件 | 各系统行为 |
|---|---|
| 触发场景切换 | 世界系统发出 OnSceneTransitionBegin |
| 过渡动画播放 | UI 系统显示过渡遮罩;输入系统暂停接收 |
| 旧场景卸载 | 敌人系统、VFX 等局部系统销毁 |
| 新场景加载 | 世界系统重建房间;敌人系统重新初始化 |
| 玩家状态恢复 | 玩家系统将 HP/技能应用至新场景(不重置) |
| 切换完成 | 世界系统发出 OnSceneTransitionEnd;输入系统恢复 |
7.3 死亡与复活流程
玩家 HP 降至 0
→ 玩家系统发出 OnPlayerDied
→ 输入系统:禁止所有输入
→ UI 系统:播放死亡遮罩动画
→ 音频系统:切换至死亡音乐
→ 存档系统:记录死亡位置(遗骸数据)
→ 世界系统:在上次死亡位置生成遗骸实体
等待(玩家按键或自动)→ 触发复活
复活流程:
→ 世界系统:加载最近存档点所在场景
→ 玩家系统:恢复存档时的 HP / 灵泉次数(见存档规范)
→ 输入系统:恢复输入
→ UI 系统:淡出遮罩
→ 音频系统:恢复区域音乐
附:常见架构陷阱与规避方法
| 陷阱 | 典型表现 | 规避方法 |
|---|---|---|
| 上帝对象 | 一个系统知道所有其他系统的状态 | 拆分为多个专责系统 |
| 循环依赖 | A 依赖 B,B 依赖 A | 引入事件频道或接口打断循环 |
| 隐式顺序耦合 | 系统 A 必须在 B 之后执行才正确 | 改用事件触发替代时序依赖 |
| 状态同步噩梦 | 多个系统各自维护同一份数据的副本 | 确立唯一所有者,其他系统订阅变化 |
| 胖配置数据 | 配置数据里混入运行时逻辑 | 严格区分 Config 和 RuntimeState |