chore: initial commit
This commit is contained in:
269
Docs/DesignSpec/00_DesignConventions.md
Normal file
269
Docs/DesignSpec/00_DesignConventions.md
Normal file
@@ -0,0 +1,269 @@
|
||||
# 00 · 设计规范与符号约定
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **用途**:阅读本文档集前的必读指南,定义所有文档统一使用的符号、术语和格式约定。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [文档定位原则](#1-文档定位原则)
|
||||
2. [抽象数据类型](#2-抽象数据类型)
|
||||
3. [数据模型符号](#3-数据模型符号)
|
||||
4. [接口契约符号](#4-接口契约符号)
|
||||
5. [状态机符号](#5-状态机符号)
|
||||
6. [事件符号](#6-事件符号)
|
||||
7. [系统依赖符号](#7-系统依赖符号)
|
||||
8. [参数表格式](#8-参数表格式)
|
||||
9. [设计决策标注](#9-设计决策标注)
|
||||
|
||||
---
|
||||
|
||||
## 1. 文档定位原则
|
||||
|
||||
### 1.1 本文档集的边界
|
||||
|
||||
| ✅ 应包含 | ❌ 不应包含 |
|
||||
|----------|-----------|
|
||||
| 系统的功能目标(做什么)| 特定引擎的组件名称(MonoBehaviour、Node 等)|
|
||||
| 数据模型与字段语义 | 特定语言的代码语法 |
|
||||
| 系统间的通信契约 | 特定插件/库的调用方式 |
|
||||
| 状态机的状态与转换规则 | 文件系统路径、资产命名规范 |
|
||||
| 行为触发的条件与结果 | 引擎内部执行顺序(Update、FixedUpdate)|
|
||||
| 配置参数的含义与推荐范围 | Inspector 字段序列化细节 |
|
||||
| 设计决策的原因(Why)| 代码模块的命名空间划分 |
|
||||
|
||||
### 1.2 阅读层次
|
||||
|
||||
```
|
||||
本文档集(DesignSpec)
|
||||
↓ 解释"做什么、为什么"
|
||||
|
||||
Docs/Architecture(引擎架构文档)
|
||||
↓ 解释"代码如何组织、各模块如何实现"
|
||||
|
||||
实际代码
|
||||
↓ 最终实现
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 抽象数据类型
|
||||
|
||||
本文档集使用以下引擎无关的抽象类型:
|
||||
|
||||
| 符号 | 含义 | 示例 |
|
||||
|------|------|------|
|
||||
| `Integer` | 整数 | `hp: Integer` |
|
||||
| `Number` | 浮点数 | `speed: Number` |
|
||||
| `Boolean` | 布尔值 | `isGrounded: Boolean` |
|
||||
| `String` | 字符串 | `id: String` |
|
||||
| `ID` | 唯一标识符(字符串或枚举)| `formId: ID` |
|
||||
| `List<T>` | 有序列表 | `skills: List<SkillData>` |
|
||||
| `Map<K,V>` | 键值映射 | `flagMap: Map<String, Boolean>` |
|
||||
| `Optional<T>` | 可为空的值 | `target: Optional<Entity>` |
|
||||
| `Ref<T>` | 对另一数据模型的引用 | `weapon: Ref<WeaponData>` |
|
||||
| `Enum` | 枚举类型(正文中明确列出所有值)| `DamageType` |
|
||||
| `Flags` | 可组合的位标记集 | `DamageFlags` |
|
||||
| `Duration` | 时间长度(秒)| `stunDuration: Duration` |
|
||||
| `Vector2` | 二维方向或坐标 | `knockbackDir: Vector2` |
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据模型符号
|
||||
|
||||
数据模型描述一组字段的结构,**不含逻辑**,类似数据表或结构体:
|
||||
|
||||
```
|
||||
DataModel ModelName {
|
||||
fieldName : Type // 字段说明
|
||||
fieldName : Type = default // 带默认值
|
||||
fieldName : Optional<Type> // 可选字段
|
||||
──────────────────────────────── // 分隔线表示分组
|
||||
groupedField : Type // 同组字段
|
||||
}
|
||||
```
|
||||
|
||||
### 示例
|
||||
|
||||
```
|
||||
DataModel DamagePacket {
|
||||
rawDamage : Integer // 基础伤害
|
||||
damageType : DamageType // 伤害类型枚举
|
||||
knockbackDir : Vector2 // 击退方向(单位向量)
|
||||
knockbackForce : Number // 击退力度
|
||||
stunDuration : Duration // 硬直时长(秒)
|
||||
flags : Flags<DamageFlags>
|
||||
──────────────────────────────────
|
||||
sourceId : ID // 攻击来源的唯一标识(用于特殊规则查询)
|
||||
sourcePosition : Vector2 // 攻击来源位置(计算击退方向时备用)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 接口契约符号
|
||||
|
||||
接口描述一个系统对外暴露的操作与属性,不规定内部实现:
|
||||
|
||||
```
|
||||
Interface IInterfaceName {
|
||||
|
||||
// 只读属性
|
||||
[readonly] propertyName : Type
|
||||
|
||||
// 可写属性
|
||||
[readwrite] propertyName : Type
|
||||
|
||||
// 方法:方法名(参数名: 类型, …) → 返回类型
|
||||
// 若无返回值写 void
|
||||
methodName(param: Type) → ReturnType
|
||||
|
||||
// 可失败的方法(返回 Result)
|
||||
methodName(param: Type) → Result<ReturnType>
|
||||
|
||||
// 事件(外部可订阅)
|
||||
[event] onSomething : EventType
|
||||
}
|
||||
```
|
||||
|
||||
### 示例
|
||||
|
||||
```
|
||||
Interface IHealthOwner {
|
||||
[readonly] currentHP : Integer
|
||||
[readonly] maxHP : Integer
|
||||
[readonly] isAlive : Boolean
|
||||
|
||||
takeDamage(packet: DamagePacket) → void
|
||||
heal(amount: Integer) → void
|
||||
[event] onHPChanged : Event<HPChangedPayload>
|
||||
[event] onDied : Event<void>
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 状态机符号
|
||||
|
||||
### 5.1 状态定义
|
||||
|
||||
```
|
||||
State StateName {
|
||||
priority : Integer // 数字越大、越难被低优先级状态打断
|
||||
interruptBy: List<State> // 可被哪些状态强制打断
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 状态转换图
|
||||
|
||||
```
|
||||
[StateA]
|
||||
──条件──► [StateB] // 正常转换
|
||||
══强制══► [StateC] // 强制(忽略优先级)
|
||||
~~超时~~► [StateD] // 超时自动转换
|
||||
|
||||
[StateB]
|
||||
──落地────────────► [IdleState]
|
||||
──攻击输入─────────► [AttackState]
|
||||
```
|
||||
|
||||
### 5.3 转换条件格式
|
||||
|
||||
| 符号 | 含义 |
|
||||
|------|------|
|
||||
| `──条件──►` | 满足条件后转换 |
|
||||
| `══强制══►` | 外部强制调用,跳过优先级检查 |
|
||||
| `~~超时~~►` | 经过 N 秒后自动转换 |
|
||||
| `[condition AND condition]` | 复合条件 |
|
||||
| `[NOT condition]` | 条件取反 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 事件符号
|
||||
|
||||
事件用于系统间的解耦通知,只传递最小必要数据:
|
||||
|
||||
```
|
||||
Event EventName {
|
||||
payload: PayloadType // 携带的数据,void 表示无数据
|
||||
emitter: SystemName // 哪个系统发出
|
||||
listeners: [SystemA, SystemB, ...] // 典型订阅方(非强制)
|
||||
}
|
||||
```
|
||||
|
||||
### 事件目录格式
|
||||
|
||||
| 事件名 | 载荷类型 | 发出方 | 用途 |
|
||||
|--------|---------|--------|------|
|
||||
| `OnPlayerDied` | `void` | 玩家系统 | 触发复活流程 |
|
||||
| `OnHPChanged` | `{current, max}` | 玩家系统 | 更新 HUD |
|
||||
|
||||
---
|
||||
|
||||
## 7. 系统依赖符号
|
||||
|
||||
系统之间的依赖关系通过以下格式表达:
|
||||
|
||||
```
|
||||
SystemA ──读取──► DataModel // 读取数据
|
||||
SystemA ──写入──► DataModel // 写入数据
|
||||
SystemA ──发出──► EventX // 发出事件
|
||||
SystemA ◄─订阅── EventY // 订阅事件
|
||||
SystemA ──调用──► IInterface // 调用接口方法
|
||||
|
||||
系统间不应出现:
|
||||
SystemA ──直接引用──► SystemB // ❌ 禁止直接持有另一系统引用
|
||||
```
|
||||
|
||||
### 依赖等级
|
||||
|
||||
| 等级 | 说明 |
|
||||
|------|------|
|
||||
| **强依赖**(编译时)| A 的存在必须依赖 B 的接口定义 |
|
||||
| **弱依赖**(运行时事件)| A 通过事件通知 B,B 不存在时 A 仍可正常运行 |
|
||||
| **数据依赖**(只读配置)| A 读取共享配置数据,无运行时交互 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 参数表格式
|
||||
|
||||
配置参数表统一格式:
|
||||
|
||||
| 参数名 | 类型 | 推荐值 | 说明 | 调整影响 |
|
||||
|--------|------|--------|------|---------|
|
||||
| `walkSpeed` | Number | 6.0 | 地面行走速度(单位/秒)| 越高越灵活,越低越沉重 |
|
||||
| `jumpForce` | Number | 16.0 | 跳跃初速度 | 越高跳跃越高,需同步调整重力 |
|
||||
|
||||
> **调整原则**:每次只修改一个参数,实测手感后确认。参数间存在联动关系时,文档中注明。
|
||||
|
||||
---
|
||||
|
||||
## 9. 设计决策标注
|
||||
|
||||
文档中的设计决策用以下格式标注原因,方便日后回溯:
|
||||
|
||||
```
|
||||
> **设计决策**:[决策内容]
|
||||
> **原因**:[为什么这样设计]
|
||||
> **替代方案**:[考虑过但未选用的方案及原因]
|
||||
```
|
||||
|
||||
### 示例
|
||||
|
||||
> **设计决策**:弹反成功后增加 +33 灵力,而非固定值
|
||||
> **原因**:鼓励玩家主动弹反,弹反本身是高风险操作,大幅奖励使弹反策略具有可行的资源通路
|
||||
> **替代方案**:弹反+0 灵力(纯战斗技巧),但测试发现玩家没有足够动机学习弹反
|
||||
|
||||
---
|
||||
|
||||
## 附:文档写作检查清单
|
||||
|
||||
在向本文档集新增或修改文档时,请确认:
|
||||
|
||||
- [ ] 所有数据类型使用抽象类型(不出现 `int`, `float`, `string`, `MonoBehaviour` 等)
|
||||
- [ ] 所有引擎功能通过行为描述替代("物理检测地面"而非"OverlapBox")
|
||||
- [ ] 系统接口以契约格式定义,不包含实现细节
|
||||
- [ ] 参数表包含"调整影响"列
|
||||
- [ ] 重要设计决策附有原因说明
|
||||
- [ ] 文档末尾无悬空的"TODO"或临时注记
|
||||
278
Docs/DesignSpec/01_SystemArchitecture.md
Normal file
278
Docs/DesignSpec/01_SystemArchitecture.md
Normal file
@@ -0,0 +1,278 @@
|
||||
# 01 · 系统架构总览
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:定义游戏的核心设计哲学、系统全景图、模块边界与系统间通信规范。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [设计哲学](#1-设计哲学)
|
||||
2. [系统全景图](#2-系统全景图)
|
||||
3. [系统分层模型](#3-系统分层模型)
|
||||
4. [通信模式规范](#4-通信模式规范)
|
||||
5. [数据层与逻辑层分离](#5-数据层与逻辑层分离)
|
||||
6. [模块边界原则](#6-模块边界原则)
|
||||
7. [系统优先级与生命周期](#7-系统优先级与生命周期)
|
||||
|
||||
---
|
||||
|
||||
## 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 边界定义规则
|
||||
|
||||
系统的边界由以下三要素确定:
|
||||
|
||||
1. **输入**:系统响应的事件 + 调用的接口
|
||||
2. **输出**:系统发出的事件 + 对外提供的接口
|
||||
3. **状态**:系统独占写权限的运行时数据
|
||||
|
||||
### 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 |
|
||||
173
Docs/DesignSpec/02_EventMessaging.md
Normal file
173
Docs/DesignSpec/02_EventMessaging.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# 02 · 事件与消息系统规范
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:定义游戏全局的事件通信规范、事件目录与发布/订阅契约。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [事件系统设计原则](#1-事件系统设计原则)
|
||||
2. [事件类型体系](#2-事件类型体系)
|
||||
3. [发布/订阅契约](#3-发布订阅契约)
|
||||
4. [全局事件目录](#4-全局事件目录)
|
||||
5. [事件设计指导](#5-事件设计指导)
|
||||
|
||||
---
|
||||
|
||||
## 1. 事件系统设计原则
|
||||
|
||||
| 原则 | 说明 |
|
||||
|------|------|
|
||||
| **最小载荷** | 事件只携带消费方需要的最少信息 |
|
||||
| **类型安全** | 每个事件有明确的载荷类型,不使用无类型通用事件 |
|
||||
| **无副作用传递** | 事件不携带可修改的对象引用,防止订阅方意外修改状态 |
|
||||
| **单向通知** | 事件只通知"发生了什么",不携带"如何处理"的指令 |
|
||||
| **有限生命周期** | 事件在发出后立即处理,不在系统间长期持有 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 事件类型体系
|
||||
|
||||
### 2.1 按载荷分类
|
||||
|
||||
| 类型 | 描述 | 适用场景 |
|
||||
|------|------|---------|
|
||||
| `Event<void>` | 无载荷事件,纯通知 | 玩家死亡、游戏暂停 |
|
||||
| `Event<T>` | 单值载荷 | HP 变化(传入新值)|
|
||||
| `Event<Payload>` | 结构体载荷 | 伤害事件(多字段)|
|
||||
|
||||
### 2.2 按作用范围分类
|
||||
|
||||
| 类型 | 作用范围 | 说明 |
|
||||
|------|---------|------|
|
||||
| **全局事件** | 全游戏有效,跨场景 | 玩家死亡、游戏暂停、存档完成 |
|
||||
| **局部事件** | 单场景/房间内有效 | 敌人死亡、机关触发、Boss 阶段变更 |
|
||||
| **实体事件** | 单个实体范围 | 单个 NPC 对话开始、单个陷阱激活 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 发布/订阅契约
|
||||
|
||||
### 3.1 发布方契约
|
||||
|
||||
发布方(Emitter)必须:
|
||||
- 在系统初始化时注册事件频道
|
||||
- 仅在状态确实发生变化时发出事件(不重复发出相同状态)
|
||||
- 在系统销毁时清理事件频道
|
||||
|
||||
### 3.2 订阅方契约
|
||||
|
||||
订阅方(Listener)必须:
|
||||
- 在系统初始化时注册订阅
|
||||
- 在系统销毁时取消订阅(防止悬挂引用)
|
||||
- 不在事件处理中再发出同类型事件(防止递归循环)
|
||||
|
||||
### 3.3 事件处理顺序
|
||||
|
||||
当多个系统订阅同一事件时,处理顺序**不保证**。
|
||||
任何依赖特定顺序的逻辑应通过**新增中间事件**拆分为有序的因果链,而非依赖底层执行顺序。
|
||||
|
||||
```
|
||||
❌ 错误:期望 A 先处理,B 后处理同一事件
|
||||
✅ 正确:A 处理事件后发出新事件,B 订阅新事件
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 全局事件目录
|
||||
|
||||
### 4.1 玩家相关事件
|
||||
|
||||
| 事件名 | 载荷类型 | 发出方 | 典型订阅方 | 触发时机 |
|
||||
|--------|---------|--------|----------|---------|
|
||||
| `OnPlayerDied` | `void` | 玩家系统 | UI、音频、存档、世界 | 玩家 HP 归零 |
|
||||
| `OnPlayerRevived` | `void` | 游戏管理器 | 玩家系统、UI、音频 | 复活流程完成 |
|
||||
| `OnHPChanged` | `{current: Integer, max: Integer}` | 玩家系统 | UI(HUD)| HP 任意变化 |
|
||||
| `OnSoulPowerChanged` | `{current: Integer, max: Integer}` | 玩家系统 | UI(HUD)| 灵力变化 |
|
||||
| `OnSpiritPowerChanged` | `{current: Integer, max: Integer}` | 玩家系统 | UI(HUD)| 魄元变化 |
|
||||
| `OnSpringChargesChanged` | `{current: Integer, max: Integer}` | 玩家系统 | UI(HUD)| 灵泉次数变化 |
|
||||
| `OnGeoChanged` | `{current: Integer, delta: Integer}` | 经济系统 | UI(HUD)| Geo 增减 |
|
||||
| `OnAbilityUnlocked` | `{abilityId: ID}` | 进程系统 | 玩家系统、UI | 新能力获得 |
|
||||
| `OnFormChanged` | `{newFormId: ID}` | 形态系统 | UI、音频、武器系统 | 玩家切换形态 |
|
||||
| `OnParrySuccess` | `{counterWindowDuration: Duration}` | 战斗系统 | 玩家系统、UI、音频 | 弹反判定成功 |
|
||||
| `OnHitConfirmed` | `HitPayload` | 战斗系统 | 玩家系统(灵力积累)、反馈系统 | 攻击命中判定 |
|
||||
|
||||
### 4.2 敌人相关事件
|
||||
|
||||
| 事件名 | 载荷类型 | 发出方 | 典型订阅方 | 触发时机 |
|
||||
|--------|---------|--------|----------|---------|
|
||||
| `OnEnemyDied` | `{enemyId: ID, position: Vector2}` | 敌人系统 | 进程系统、经济系统、叙事系统 | 敌人 HP 归零 |
|
||||
| `OnEnemyHit` | `HitPayload` | 战斗系统 | 反馈系统、音频 | 攻击命中敌人 |
|
||||
| `OnBossPhaseChanged` | `{bossId: ID, phase: Integer}` | Boss 系统 | UI、音频 | Boss 进入新阶段 |
|
||||
| `OnBossDefeated` | `{bossId: ID}` | 敌人系统 | 进程系统、叙事系统、存档 | Boss 战胜利 |
|
||||
|
||||
### 4.3 世界/进程相关事件
|
||||
|
||||
| 事件名 | 载荷类型 | 发出方 | 典型订阅方 | 触发时机 |
|
||||
|--------|---------|--------|----------|---------|
|
||||
| `OnSceneTransitionBegin` | `{targetSceneId: ID}` | 世界系统 | UI(遮罩)、输入系统 | 开始场景切换 |
|
||||
| `OnSceneTransitionEnd` | `{sceneId: ID}` | 世界系统 | 输入系统、音频 | 场景切换完成 |
|
||||
| `OnSavePointActivated` | `{savePointId: ID, position: Vector2}` | 世界系统 | 存档系统、玩家系统、UI | 玩家激活存档点 |
|
||||
| `OnRoomDiscovered` | `{roomId: ID}` | 世界系统 | 地图系统 | 玩家首次进入房间 |
|
||||
| `OnCollectiblePickedUp` | `{collectibleId: ID, type: CollectibleType}` | 世界系统 | 进程系统、叙事系统 | 玩家拾取收集品 |
|
||||
| `OnWorldFlagChanged` | `{flagId: ID, value: Boolean}` | 叙事系统 | 叙事系统(自引用)、进程系统 | 世界状态标志变化 |
|
||||
|
||||
### 4.4 UI/系统相关事件
|
||||
|
||||
| 事件名 | 载荷类型 | 发出方 | 典型订阅方 | 触发时机 |
|
||||
|--------|---------|--------|----------|---------|
|
||||
| `OnGamePaused` | `void` | 游戏管理器 | 所有系统 | 暂停键触发 |
|
||||
| `OnGameResumed` | `void` | 游戏管理器 | 所有系统 | 恢复键触发 |
|
||||
| `OnSaveCompleted` | `{slotId: Integer}` | 存档系统 | UI(提示)| 存档写入完成 |
|
||||
| `OnSettingsChanged` | `SettingsPayload` | 设置系统 | 音频、无障碍、UI 等 | 设置项变更 |
|
||||
| `OnAchievementUnlocked` | `{achievementId: ID}` | 成就系统 | UI(Toast)| 成就达成 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 事件设计指导
|
||||
|
||||
### 5.1 新增事件时的决策流程
|
||||
|
||||
```
|
||||
需要系统 A 通知系统 B 时:
|
||||
|
||||
B 是否需要立即同步返回值?
|
||||
├─ 是 → 使用接口调用(不是事件)
|
||||
└─ 否 → 使用事件
|
||||
|
||||
事件是否跨多个系统关心?
|
||||
├─ 是(多个系统订阅)→ 定义为全局事件,加入全局目录
|
||||
└─ 否(仅 A→B)→ 考虑是否用接口更合适
|
||||
|
||||
事件是否携带可变对象引用?
|
||||
├─ 是 → 改为传递值类型载荷(ID + 必要字段)
|
||||
└─ 否 → 可以使用
|
||||
```
|
||||
|
||||
### 5.2 载荷设计规范
|
||||
|
||||
**好的载荷(值类型,信息完整)**:
|
||||
```
|
||||
OnEnemyDied {
|
||||
enemyId : ID // 唯一标识,订阅方可用于查询更多信息
|
||||
position : Vector2 // 死亡位置(生成掉落物需要)
|
||||
lootTableId : ID // 掉落表 ID(经济系统直接使用)
|
||||
}
|
||||
```
|
||||
|
||||
**不好的载荷(引用传递,导致耦合)**:
|
||||
```
|
||||
OnEnemyDied {
|
||||
enemyRef : EnemyObject // ❌ 引用具体对象,订阅方与敌人系统耦合
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 事件命名规范
|
||||
|
||||
| 规范 | 说明 | 示例 |
|
||||
|------|------|------|
|
||||
| 动词过去式(On + 名词 + 动词过去式)| 表示"已发生的事" | `OnPlayerDied`、`OnAbilityUnlocked` |
|
||||
| 变化类用 Changed | 状态数值变化 | `OnHPChanged`、`OnGeoChanged` |
|
||||
| 开始/结束对 | 持续性事件标注阶段 | `OnSceneTransitionBegin` / `OnSceneTransitionEnd` |
|
||||
| 避免"Will/Should" | 事件是通知,不是征询许可 | ❌ `OnPlayerWillDie`,✅ `OnPlayerDied` |
|
||||
332
Docs/DesignSpec/03_PlayerSystem.md
Normal file
332
Docs/DesignSpec/03_PlayerSystem.md
Normal file
@@ -0,0 +1,332 @@
|
||||
# 03 · 玩家系统规范
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:玩家实体的构成、资源模型、状态机规范与对外行为契约。
|
||||
> **关联**:[04_CombatSystem](./04_CombatSystem.md) · [05_MovementSystem](./05_MovementSystem.md) · [06_FormSystem](./06_FormSystem.md)
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [玩家实体构成](#1-玩家实体构成)
|
||||
2. [资源模型](#2-资源模型)
|
||||
3. [玩家状态机](#3-玩家状态机)
|
||||
4. [行为契约](#4-行为契约)
|
||||
5. [能力解锁体系](#5-能力解锁体系)
|
||||
6. [玩家配置参数](#6-玩家配置参数)
|
||||
7. [发出的事件](#7-发出的事件)
|
||||
|
||||
---
|
||||
|
||||
## 1. 玩家实体构成
|
||||
|
||||
玩家实体是多个**职责分离的子系统**的协调器,自身不含具体业务逻辑:
|
||||
|
||||
```
|
||||
PlayerEntity(协调器)
|
||||
├── MovementController ← 物理移动(速度、跳跃、冲刺)
|
||||
├── StatContainer ← 资源数值(HP、灵力、魄元、灵泉、Geo)
|
||||
├── CombatHandler ← 攻击判定(HitBox 开关、连击链)
|
||||
├── FormController ← 形态管理(天魂/地魂/命魂切换)
|
||||
├── WeaponSlot ← 当前武器(形态联动自动切换)
|
||||
├── SkillExecutor ← 技能执行(魂技能/魄技能)
|
||||
├── ParryHandler ← 弹反逻辑
|
||||
├── HurtBox ← 受击判定(路由 DamagePacket)
|
||||
└── StateMachine ← 行为状态机(协调上述子系统)
|
||||
```
|
||||
|
||||
**协调器原则**:PlayerEntity 只负责:
|
||||
1. 初始化子系统并维护引用
|
||||
2. 维护状态机(决定当前行为)
|
||||
3. 在受击时强制转换到受击状态
|
||||
4. 在死亡时触发 `OnPlayerDied` 事件
|
||||
|
||||
---
|
||||
|
||||
## 2. 资源模型
|
||||
|
||||
### 2.1 资源总览
|
||||
|
||||
| 资源 | 类型 | 范围 | 特性 | 用途 |
|
||||
|------|------|------|------|------|
|
||||
| **HP** | Integer | 0 ~ MaxHP | 受击减少,存档点/灵泉恢复 | 生存指标 |
|
||||
| **灵力(SoulPower)** | Integer | 0 ~ 100 | 近战命中积累,死亡清零 | 魂技能燃料 |
|
||||
| **魄元(SpiritPower)** | Integer | 0 ~ 100 | 时间自动恢复,死亡恢复至上限 | 魄技能燃料 |
|
||||
| **灵泉次数(SpringCharges)** | Integer | 0 ~ MaxCharges | 击杀积分驱动,存档点恢复 | 治疗次数 |
|
||||
| **Geo(灵晶)** | Integer | 0 ~ ∞ | 击败敌人获得,死亡遗留遗骸 | 货币 |
|
||||
|
||||
### 2.2 灵力积累规则
|
||||
|
||||
> **设计目标**:鼓励玩家主动攻击,弹反作为高回报行为
|
||||
|
||||
| 来源 | 灵力增量 |
|
||||
|------|---------|
|
||||
| 近战命中普通敌人 | +10 |
|
||||
| 近战命中 Boss | +5 |
|
||||
| 弹反成功 | +33 |
|
||||
|
||||
- 死亡时归零
|
||||
- 无自动恢复
|
||||
|
||||
### 2.3 魄元恢复规则
|
||||
|
||||
> **设计目标**:魄元是始终可用的"持续消耗"资源,不依赖风险操作
|
||||
|
||||
| 来源 | 魄元增量 |
|
||||
|------|---------|
|
||||
| 每秒自动恢复 | +`spiritRegenRate`(见配置参数)|
|
||||
| 死亡复活 | 恢复至上限 |
|
||||
| 存档点交互 | 恢复至上限 |
|
||||
|
||||
- 受伤不影响魄元
|
||||
- 使用魄技能后扣除固定量
|
||||
|
||||
### 2.4 灵泉次数规则
|
||||
|
||||
> **设计目标**:治疗是"击杀驱动"而非"时间驱动",鼓励激进战斗风格
|
||||
|
||||
| 来源 | 变化 |
|
||||
|------|------|
|
||||
| 击杀普通敌人 | +1 积分 |
|
||||
| 击杀精英怪 | +3 积分 |
|
||||
| 击杀 Boss | +5 积分 |
|
||||
| 积分达到阈值 | +1 次灵泉(积分清零)|
|
||||
| 使用灵泉(治疗)| -1 次 |
|
||||
| 与存档点交互 | 恢复至上限 |
|
||||
| 死亡复活 | **不恢复**(死亡惩罚)|
|
||||
|
||||
> **设计决策**:死亡不恢复灵泉
|
||||
> **原因**:保留一定死亡惩罚,让玩家珍惜治疗机会,但由于复活在存档点旁,玩家仍可快速通过激活存档点补满
|
||||
|
||||
### 2.5 Geo(货币)规则
|
||||
|
||||
| 来源 | 变化 |
|
||||
|------|------|
|
||||
| 击败敌人 | 掉落固定 + 随机范围 |
|
||||
| 破坏场景容器 | 少量固定 |
|
||||
| 任务奖励 | 固定量 |
|
||||
| 死亡 | Geo 留在遗骸,不直接丢失 |
|
||||
| 取回遗骸 | 遗骸的 Geo 归还玩家 |
|
||||
| 再次死亡(未取回遗骸)| 遗骸 Geo **永久丢失** |
|
||||
|
||||
---
|
||||
|
||||
## 3. 玩家状态机
|
||||
|
||||
### 3.1 状态优先级
|
||||
|
||||
| 优先级 | 状态 | 说明 |
|
||||
|--------|------|------|
|
||||
| 100 | `DeathState` | 死亡,不可被任何状态打断 |
|
||||
| 90 | `HurtState` | 受击硬直,仅死亡可打断 |
|
||||
| 80 | `DashState` | 冲刺(含空中冲刺),受伤/死亡可打断 |
|
||||
| 75 | `SoulSkillState` | 魂技能前摇,冲刺/受伤可打断 |
|
||||
| 72 | `SpiritSkillState` | 魄技能前摇,冲刺/受伤可打断 |
|
||||
| 70 | `ParryState` | 弹反等待,受伤可打断 |
|
||||
| 60 | `AttackState` | 攻击,弹反/受伤可打断 |
|
||||
| 55 | `SpringState` | 使用灵泉,前摇可被打断 |
|
||||
| 40 | `InteractState` | 与 NPC/物件交互 |
|
||||
| 35 | `WallGrabState` | 抓墙悬挂,冲刺/技能可打断 |
|
||||
| 30 | `AirState` | 空中(含跳跃/下落)|
|
||||
| 20 | `RunState` | 地面奔跑 |
|
||||
| 10 | `SwimState` | 游泳(解锁后)|
|
||||
| 0 | `IdleState` | 待机(最低优先级)|
|
||||
|
||||
### 3.2 状态转换规则
|
||||
|
||||
```
|
||||
任意状态
|
||||
══受击(HP>0)══► HurtState [强制,忽略优先级]
|
||||
══受击(HP=0)══► DeathState [强制,不可被打断]
|
||||
|
||||
IdleState
|
||||
──移动输入──────────► RunState
|
||||
──跳跃输入──────────► AirState
|
||||
──攻击输入──────────► AttackState
|
||||
──弹反输入──────────► ParryState
|
||||
──冲刺输入──────────► DashState
|
||||
──魂技能+灵力充足───► SoulSkillState
|
||||
──魄技能+魄元充足───► SpiritSkillState
|
||||
──使用灵泉+次数≥1──► SpringState
|
||||
──交互输入+目标存在─► InteractState
|
||||
|
||||
RunState
|
||||
──无移动输入─────────► IdleState
|
||||
──跳跃输入───────────► AirState
|
||||
──攻击输入───────────► AttackState(保持RunState,上半身叠加)
|
||||
──弹反/冲刺/技能─────► 对应状态
|
||||
|
||||
AirState(统一处理 跳跃/双跳/下落)
|
||||
──落地───────────────► IdleState 或 RunState
|
||||
──跳跃输入+双跳可用──► AirState内重置(双跳,不切状态)
|
||||
──贴墙+朝墙方向输入──► WallGrabState
|
||||
──攻击/弹反/冲刺─────► 对应状态
|
||||
|
||||
WallGrabState
|
||||
──跳跃输入───────────► AirState(蹬墙跳)
|
||||
──反向输入或落地─────► AirState / IdleState
|
||||
──冲刺/技能──────────► 对应状态
|
||||
|
||||
AttackState(上半身叠加,下半身保持原状态)
|
||||
~~动画结束~~──────────► 恢复原状态(Idle/Run/Air)
|
||||
──连击窗口内攻击输入─► AttackState(切换连击段)
|
||||
──弹反输入───────────► ParryState
|
||||
|
||||
ParryState
|
||||
──弹反成功───────────► ParrySuccessState(反击窗口)
|
||||
──攻击输入(窗口内)─► AttackState(ParryCounter)
|
||||
~~反击窗口超时~~─────► IdleState/RunState
|
||||
~~弹反超时~~──────────► IdleState/RunState
|
||||
|
||||
DashState
|
||||
~~冲刺时长结束~~────── ► AirState 或 IdleState/RunState
|
||||
|
||||
SpringState
|
||||
~~前摇完成~~──────────► 后摇 → IdleState
|
||||
──被打断─────────────► IdleState(灵泉次数已扣,不返还)
|
||||
|
||||
HurtState
|
||||
~~硬直时长结束~~──────► IdleState
|
||||
|
||||
DeathState
|
||||
(等待游戏管理器触发复活流程)
|
||||
```
|
||||
|
||||
### 3.3 攻击连击链
|
||||
|
||||
| 连击段 | 触发方式 | 攻击方向 | 伤害倍率 | 备注 |
|
||||
|--------|---------|---------|---------|------|
|
||||
| `Attack1` | 第一次攻击输入 | 水平 | ×1.0 | 各形态动画不同 |
|
||||
| `Attack2` | 连击窗口内再攻击 | 水平 | ×1.0 | |
|
||||
| `Attack3` | 连击窗口内再攻击 | 水平 | ×2.0 | 重击,连击链结尾 |
|
||||
| `AirAttack` | 空中攻击 | 水平 | ×1.0 | |
|
||||
| `UpAttack` | 移动方向向上时攻击 | 向上 | ×1.0 | 角色轻微下移(反作用力)|
|
||||
| `DownAttack` | 空中+移动方向向下时攻击 | 向下 | ×1.0 | 命中时产生弹起(Pogo)|
|
||||
| `ParryCounter` | 弹反成功后攻击 | 水平 | ×3.0 | 不可被弹反,忽略无敌帧 |
|
||||
|
||||
> **设计决策**:第三击伤害 ×2,弹反反击 ×3
|
||||
> **原因**:鼓励打满连击,奖励弹反技巧。高倍率使玩家有显著的策略目标。
|
||||
|
||||
---
|
||||
|
||||
## 4. 行为契约
|
||||
|
||||
### 4.1 玩家实体对外接口
|
||||
|
||||
```
|
||||
Interface IPlayerEntity {
|
||||
// 只读属性
|
||||
[readonly] position : Vector2
|
||||
[readonly] facingDirection : Integer // +1 右 / -1 左
|
||||
[readonly] currentState : StateID
|
||||
[readonly] isInvincible : Boolean
|
||||
|
||||
// 强制状态切换(外部系统使用,如受击)
|
||||
forceState(stateId: StateID, context: Optional<StateContext>) → void
|
||||
|
||||
// 查询
|
||||
hasAbility(abilityId: ID) → Boolean
|
||||
|
||||
// 事件
|
||||
[event] onDied : Event<void>
|
||||
[event] onHit : Event<HitPayload>
|
||||
[event] onStateChanged : Event<StateChangedPayload>
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 StatContainer 对外接口
|
||||
|
||||
```
|
||||
Interface IStatContainer {
|
||||
[readonly] currentHP : Integer
|
||||
[readonly] maxHP : Integer
|
||||
[readonly] currentSoulPower : Integer
|
||||
[readonly] currentSpiritPower : Integer
|
||||
[readonly] currentSpringCharges: Integer
|
||||
[readonly] maxSpringCharges : Integer
|
||||
[readonly] currentGeo : Integer
|
||||
[readonly] isAlive : Boolean
|
||||
|
||||
takeDamage(amount: Integer) → void
|
||||
heal(amount: Integer) → void
|
||||
addSoulPower(amount: Integer) → void
|
||||
consumeSoulPower(amount: Integer) → Result<Boolean>
|
||||
consumeSpiritPower(amount: Integer) → Result<Boolean>
|
||||
addKillCredit(creditType: KillType) → void // 驱动灵泉积分
|
||||
useSpring() → Result<Boolean>
|
||||
restoreSpringCharges() → void
|
||||
addGeo(amount: Integer) → void
|
||||
spendGeo(amount: Integer) → Result<Boolean>
|
||||
beginInvincibility(duration: Duration)→ void
|
||||
|
||||
[event] onHPChanged : Event<{current, max}>
|
||||
[event] onSoulPowerChanged : Event<{current, max}>
|
||||
[event] onSpiritPowerChanged : Event<{current, max}>
|
||||
[event] onSpringChargesChanged : Event<{current, max}>
|
||||
[event] onGeoChanged : Event<{current, delta}>
|
||||
[event] onDied : Event<void>
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 能力解锁体系
|
||||
|
||||
### 5.1 能力定义
|
||||
|
||||
| 能力 ID | 默认状态 | 影响的状态/行为 | 解锁位置 |
|
||||
|---------|---------|--------------|---------|
|
||||
| `DoubleJump` | 锁定 | AirState 允许第二次跳跃 | 探索奖励 |
|
||||
| `WallGrab` | **已解锁** | AirState → WallGrabState 允许 | 初始能力 |
|
||||
| `AerialDash` | 锁定 | AirState → DashState 允许(消耗充能)| 探索奖励 |
|
||||
| `Parry` | **已解锁** | ParryState 可进入 | 初始能力 |
|
||||
| `Swim` | 锁定 | 液体区域不死亡,SwimState 可进入 | 主线解锁 |
|
||||
| `PlungeAttack` | 锁定 | 空中向下冲刺触发下冲 | 探索奖励 |
|
||||
|
||||
### 5.2 解锁流程
|
||||
|
||||
```
|
||||
玩家触碰解锁物件(AbilityUnlockItem)
|
||||
→ 世界系统发出 OnCollectiblePickedUp(type=Ability, abilityId)
|
||||
→ 进程系统处理:将 abilityId 加入已解锁集合
|
||||
→ 进程系统发出 OnAbilityUnlocked(abilityId)
|
||||
→ 玩家系统接收:更新运行时能力标记
|
||||
→ UI 系统显示能力获得动画
|
||||
→ 存档系统:在下次存档时持久化
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 玩家配置参数
|
||||
|
||||
以下参数在配置数据中定义,运行时只读:
|
||||
|
||||
| 参数 | 类型 | 推荐值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| `maxHP` | Integer | 5 | 初始最大生命值 |
|
||||
| `maxSoulPower` | Integer | 100 | 灵力上限 |
|
||||
| `maxSpiritPower` | Integer | 100 | 魄元上限 |
|
||||
| `spiritRegenRate` | Number | 8.0/s | 魄元每秒自动回复量 |
|
||||
| `maxSpringCharges` | Integer | 3 | 初始最大灵泉次数 |
|
||||
| `springKillThreshold` | Integer | 5 | 增加 1 次灵泉所需积分 |
|
||||
| `iFrameAfterHit` | Duration | 1.2s | 受击后无敌时长 |
|
||||
| `comboWindowDuration` | Duration | 0.5s | 连击窗口时长 |
|
||||
| `comboResetDelay` | Duration | 0.3s | 第三击后连击重置延迟 |
|
||||
| `parryCounterDuration` | Duration | 0.6s | 弹反后反击窗口时长 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 发出的事件
|
||||
|
||||
| 事件 | 触发时机 | 载荷 |
|
||||
|------|---------|------|
|
||||
| `OnPlayerDied` | HP 归零 | `void` |
|
||||
| `OnHPChanged` | HP 任意变化 | `{current, max}` |
|
||||
| `OnSoulPowerChanged` | 灵力变化 | `{current, max}` |
|
||||
| `OnSpiritPowerChanged` | 魄元变化 | `{current, max}` |
|
||||
| `OnSpringChargesChanged` | 灵泉次数变化 | `{current, max}` |
|
||||
| `OnGeoChanged` | Geo 增减 | `{current, delta}` |
|
||||
| `OnFormChanged` | 形态切换 | `{newFormId}` |
|
||||
| `OnParrySuccess` | 弹反成功 | `{counterWindowDuration}` |
|
||||
| `OnHitConfirmed` | 攻击命中有效目标 | `HitPayload` |
|
||||
| `OnAbilityUnlocked` | 新能力获得 | `{abilityId}` |
|
||||
271
Docs/DesignSpec/04_CombatSystem.md
Normal file
271
Docs/DesignSpec/04_CombatSystem.md
Normal file
@@ -0,0 +1,271 @@
|
||||
# 04 · 战斗系统规范
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:伤害数据模型、命中/受击管线、弹反系统、状态效果与连击规范。
|
||||
> **关联**:[03_PlayerSystem](./03_PlayerSystem.md) · [07_EnemySystem](./07_EnemySystem.md)
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [战斗设计原则](#1-战斗设计原则)
|
||||
2. [DamagePacket — 伤害数据模型](#2-damagepacket--伤害数据模型)
|
||||
3. [命中/受击管线](#3-命中受击管线)
|
||||
4. [弹反系统](#4-弹反系统)
|
||||
5. [霸体与打断系统](#5-霸体与打断系统)
|
||||
6. [状态效果系统](#6-状态效果系统)
|
||||
7. [战斗配置参数](#7-战斗配置参数)
|
||||
|
||||
---
|
||||
|
||||
## 1. 战斗设计原则
|
||||
|
||||
| 原则 | 说明 |
|
||||
|------|------|
|
||||
| **数据驱动** | 伤害、击退、硬直全部封装在 DamagePacket 中传递,不通过直接引用 |
|
||||
| **物理解耦** | 攻击方和受击方通过碰撞区域交互,不互相持有引用 |
|
||||
| **事件广播** | 命中确认后广播事件,让灵力积累、反馈系统等独立响应 |
|
||||
| **可弹反标记** | 每次攻击明确标记是否可被弹反,由 DamagePacket.flags 决定 |
|
||||
|
||||
---
|
||||
|
||||
## 2. DamagePacket — 伤害数据模型
|
||||
|
||||
DamagePacket 是一次攻击行为的完整数据描述,**只读值类型**,在管线中传递不可修改:
|
||||
|
||||
```
|
||||
DataModel DamagePacket {
|
||||
rawDamage : Integer // 基础伤害(未经减免)
|
||||
finalDamage : Integer // 实际伤害(由受击方计算后填写)
|
||||
damageType : DamageType // 伤害类型
|
||||
flags : Flags<DamageFlags> // 属性标记
|
||||
──────────────────────────────────────
|
||||
knockbackDir : Vector2 // 击退方向(单位向量)
|
||||
knockbackForce : Number // 击退力度
|
||||
stunDuration : Duration // 受击硬直时长(秒)
|
||||
breakLevel : BreakLevel // 打断等级(影响霸体穿透)
|
||||
──────────────────────────────────────
|
||||
sourceId : ID // 攻击来源标识(用于特殊规则)
|
||||
sourcePosition : Vector2 // 攻击来源位置
|
||||
sourceLayer : AttackerType // 来源类型(玩家/敌人/环境)
|
||||
hitFxType : HitFxType // 命中特效类型
|
||||
}
|
||||
```
|
||||
|
||||
### DamageType 枚举
|
||||
|
||||
| 值 | 说明 |
|
||||
|----|------|
|
||||
| `Normal` | 普通物理伤害 |
|
||||
| `Fire` | 火焰伤害(可点燃)|
|
||||
| `Poison` | 毒素伤害(可中毒)|
|
||||
| `Void` | 虚空伤害(忽略所有减免,用于特定 Boss)|
|
||||
| `True` | 真实伤害(固定量,忽略防御)|
|
||||
| `Environmental` | 环境伤害(棘刺/熔岩)|
|
||||
|
||||
### DamageFlags 标记
|
||||
|
||||
| 标记 | 说明 |
|
||||
|------|------|
|
||||
| `CanBeParried` | 可被弹反(移动弹射物/近身攻击)|
|
||||
| `Unblockable` | 不可被格挡或弹反(特殊攻击)|
|
||||
| `IgnoreIFrame` | 忽略受击无敌帧(毒素持续伤害)|
|
||||
| `PerfectParryOnly` | 只能被完美弹反(高难度攻击)|
|
||||
| `AoE` | 范围伤害(爆炸/冲击波)|
|
||||
| `DotTick` | 持续伤害跳数(由状态效果发出)|
|
||||
|
||||
---
|
||||
|
||||
## 3. 命中/受击管线
|
||||
|
||||
### 3.1 管线流程
|
||||
|
||||
```
|
||||
攻击方激活 HitArea(攻击判定区域)
|
||||
│
|
||||
├─ 与 HurtArea(受击判定区域)发生碰撞检测
|
||||
│ └─ 确认碰撞:攻击方的 AttackerLayer 与受击方的 HurtableLayer 匹配
|
||||
│
|
||||
├─ 受击方 HurtArea 接收 DamagePacket
|
||||
│ └─ 检查:是否处于无敌帧?
|
||||
│ ├─ 是(且非 IgnoreIFrame)→ 丢弃,不处理
|
||||
│ └─ 否 → 继续
|
||||
│
|
||||
├─ 受击方计算 finalDamage
|
||||
│ └─ rawDamage × 攻击倍率 × 防御减免
|
||||
│
|
||||
├─ 受击方本地响应
|
||||
│ ├─ 扣减 HP
|
||||
│ ├─ 应用击退
|
||||
│ ├─ 进入硬直状态
|
||||
│ └─ 启动无敌帧计时
|
||||
│
|
||||
└─ 广播 OnHitConfirmed 事件(全局)
|
||||
├─ 玩家系统:攻击命中敌人 → 增加灵力
|
||||
├─ 反馈系统:播放命中特效、震屏、音效
|
||||
└─ 进程系统:记录伤害统计
|
||||
```
|
||||
|
||||
### 3.2 攻击判定区域(HitArea)规范
|
||||
|
||||
| 属性 | 说明 |
|
||||
|------|------|
|
||||
| 形状 | 矩形(主要)或圆形(AoE 攻击)|
|
||||
| 激活时机 | 由动画事件驱动(某一帧开启,某一帧关闭)|
|
||||
| 打击次数 | 默认一次攻击只打击一个目标一次 |
|
||||
| 层级过滤 | 只与己方对立层级的 HurtArea 发生碰撞 |
|
||||
|
||||
### 3.3 受击判定区域(HurtArea)规范
|
||||
|
||||
| 属性 | 说明 |
|
||||
|------|------|
|
||||
| 形状 | 矩形(贴近实体碰撞箱)|
|
||||
| 常态 | 始终激活(死亡后关闭)|
|
||||
| 无敌帧 | 无敌期间 HurtArea 不响应伤害(仍检测碰撞)|
|
||||
|
||||
---
|
||||
|
||||
## 4. 弹反系统
|
||||
|
||||
### 4.1 设计目标
|
||||
|
||||
弹反是游戏的**核心差异化机制**:
|
||||
- 高风险(窗口极短)→ 高回报(大量灵力 + 反击机会)
|
||||
- 成功弹反会产生"子弹时间"效果,强调成功感
|
||||
- 所有标记 `CanBeParried` 的攻击都可以弹反
|
||||
|
||||
### 4.2 弹反流程
|
||||
|
||||
```
|
||||
玩家按弹反键 → 进入 ParryState
|
||||
|
||||
ParryState 开始:
|
||||
├─ 弹反激活期(parryActiveWindow)开始
|
||||
│ └─ 激活期内接收到带 CanBeParried 标记的 DamagePacket
|
||||
│ → 弹反成功
|
||||
│ ├─ 丢弃该 DamagePacket(伤害不生效)
|
||||
│ ├─ 触发子弹时间(游戏速度降至 slowMotionScale,持续 hitStopDuration)
|
||||
│ ├─ 播放弹反成功动画/特效/音效
|
||||
│ ├─ 发出 OnParrySuccess 事件
|
||||
│ ├─ 为玩家增加 +33 灵力
|
||||
│ └─ 开启反击窗口(counterWindow)
|
||||
│
|
||||
~~parryActiveWindow 超时~~ → 弹反失败,回到正常状态
|
||||
|
||||
反击窗口内:
|
||||
──攻击输入──► ParryCounter 攻击(×3 伤害,不可弹反)
|
||||
~~反击窗口超时~~ → IdleState/RunState
|
||||
```
|
||||
|
||||
### 4.3 弹反参数
|
||||
|
||||
| 参数 | 推荐值 | 说明 |
|
||||
|------|--------|------|
|
||||
| `parryActiveWindow` | 0.15s | 弹反激活期(可弹反的时间窗口)|
|
||||
| `parryStartupDelay` | 0.05s | 按键到激活期的前摇 |
|
||||
| `hitStopDuration` | 0.1s | 子弹时间持续 |
|
||||
| `slowMotionScale` | 0.15 | 子弹时间游戏速度倍率(0=完全静止)|
|
||||
| `counterWindowDuration` | 0.6s | 弹反成功后的反击窗口 |
|
||||
| `parryCounterMultiplier` | 3.0 | 弹反反击伤害倍率 |
|
||||
| `soulPowerOnParry` | 33 | 弹反成功获得灵力 |
|
||||
|
||||
> **设计决策**:弹反前摇 0.05s
|
||||
> **原因**:消除"垃圾反弹"(无脑按弹反躲伤害),要求玩家预判攻击时机
|
||||
|
||||
### 4.4 弹反优先级规则
|
||||
|
||||
| 情况 | 处理 |
|
||||
|------|------|
|
||||
| 多个攻击同时到达 | 优先弹反第一个判定的攻击,其余正常受击 |
|
||||
| 弹反期间受到 `Unblockable` 攻击 | 正常受伤,弹反状态中断 |
|
||||
| 弹反期间受到 `PerfectParryOnly` | 需在激活期的前 1/3 时间内(完美窗口)|
|
||||
|
||||
---
|
||||
|
||||
## 5. 霸体与打断系统
|
||||
|
||||
### 5.1 概念
|
||||
|
||||
**霸体(Poise)**:实体在受到攻击时抵抗动作打断的能力。
|
||||
**打断等级(BreakLevel)**:一次攻击能打断多高等级霸体的能力。
|
||||
|
||||
### 5.2 等级体系
|
||||
|
||||
| 打断等级 | 含义 | 典型来源 |
|
||||
|---------|------|---------|
|
||||
| `0 - None` | 无打断力 | 环境持续伤害 |
|
||||
| `1 - Light` | 打断低级霸体 | 玩家普通攻击 |
|
||||
| `2 - Medium` | 打断中级霸体 | 玩家重击(Attack3)|
|
||||
| `3 - Heavy` | 打断高级霸体 | 弹反反击、魂技能 |
|
||||
| `4 - Force` | 无条件打断(无视霸体)| 特定 Boss 技能 |
|
||||
|
||||
### 5.3 霸体等级
|
||||
|
||||
| 霸体等级 | 含义 | 适用实体 |
|
||||
|---------|------|---------|
|
||||
| `0 - Fragile` | 任意攻击均可打断 | 普通小怪 |
|
||||
| `1 - Standard` | 普通攻击可打断 | 常规敌人 |
|
||||
| `2 - Armored` | 需重击才能打断 | 精英怪 |
|
||||
| `3 - Boss` | 仅弹反反击/强力技能可打断 | Boss |
|
||||
|
||||
### 5.4 判定规则
|
||||
|
||||
```
|
||||
attackBreakLevel >= targetPoiseLevel → 动作打断(进入受击状态)
|
||||
attackBreakLevel < targetPoiseLevel → 伤害照常,但不打断动作
|
||||
ForceBreak 标记 → 无条件打断,忽略霸体等级
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 状态效果系统
|
||||
|
||||
### 6.1 状态效果模型
|
||||
|
||||
```
|
||||
DataModel StatusEffect {
|
||||
effectId : ID
|
||||
effectType : StatusEffectType
|
||||
duration : Duration // 持续时间(0 = 永久直到治疗)
|
||||
tickInterval : Duration // DoT 跳数间隔(仅伤害类)
|
||||
damagePerTick : Integer // 每跳伤害(仅伤害类)
|
||||
stackBehavior : StackBehavior // 叠加规则
|
||||
sourceId : ID // 施加方标识
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 效果类型
|
||||
|
||||
| 类型 | 效果 | 可叠加 | 治疗方式 |
|
||||
|------|------|--------|---------|
|
||||
| `Poison` | 每 0.5s 扣 1 HP,持续 6s | 延长时间(不叠加层数)| 解毒药 / 离开毒素区 |
|
||||
| `Burn` | 每 0.3s 扣 2 HP,持续 3s | 刷新时间 | 水体 / 时间 |
|
||||
| `Stun` | 完全硬直,无法行动 | 刷新时间 | 时间 |
|
||||
| `Slow` | 移动速度 ×0.5 | 不叠加(取最强)| 时间 |
|
||||
| `Frozen` | 完全冻结,无敌但也无法行动 | 不叠加 | 火焰攻击 |
|
||||
|
||||
### 6.3 叠加规则(StackBehavior)
|
||||
|
||||
| 规则 | 说明 |
|
||||
|------|------|
|
||||
| `RefreshDuration` | 已有效果时重置持续时间 |
|
||||
| `ExtendDuration` | 已有效果时延长持续时间 |
|
||||
| `AddStack` | 叠加层数,每层独立计时 |
|
||||
| `IgnoreIfActive` | 已激活时忽略新施加 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 战斗配置参数
|
||||
|
||||
| 参数 | 推荐值 | 说明 |
|
||||
|------|--------|------|
|
||||
| `baseAttackDamage` | 10 | 玩家基础攻击伤害 |
|
||||
| `attack1Multiplier` | 1.0 | 第一击倍率 |
|
||||
| `attack2Multiplier` | 1.0 | 第二击倍率 |
|
||||
| `attack3Multiplier` | 2.0 | 第三击(重击)倍率 |
|
||||
| `parryCounterMultiplier` | 3.0 | 弹反反击倍率 |
|
||||
| `knockbackForceNormal` | 5.0 | 普通击退力度 |
|
||||
| `knockbackForceHeavy` | 10.0 | 重击击退力度 |
|
||||
| `defaultStunDuration` | 0.3s | 默认受击硬直时长 |
|
||||
| `soulPowerPerHit` | 10 | 命中普通敌人获得灵力 |
|
||||
| `soulPowerPerBossHit` | 5 | 命中 Boss 获得灵力 |
|
||||
267
Docs/DesignSpec/05_MovementSystem.md
Normal file
267
Docs/DesignSpec/05_MovementSystem.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# 05 · 移动系统规范
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:玩家移动的物理模型、跳跃机制、冲刺、墙壁力学与手感参数。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [移动设计目标](#1-移动设计目标)
|
||||
2. [地面移动](#2-地面移动)
|
||||
3. [跳跃模型](#3-跳跃模型)
|
||||
4. [冲刺系统](#4-冲刺系统)
|
||||
5. [墙壁力学](#5-墙壁力学)
|
||||
6. [空中冲刺(Aerial Dash)](#6-空中冲刺aerial-dash)
|
||||
7. [下冲(Plunge)](#7-下冲plunge)
|
||||
8. [地面与碰撞检测](#8-地面与碰撞检测)
|
||||
9. [移动配置参数](#9-移动配置参数)
|
||||
|
||||
---
|
||||
|
||||
## 1. 移动设计目标
|
||||
|
||||
| 目标 | 实现方式 |
|
||||
|------|---------|
|
||||
| **精确可控** | 即时响应方向输入,没有"滑动"惯性 |
|
||||
| **灵活多样** | 多种移动选项(跳跃、冲刺、墙跳、空中冲刺)|
|
||||
| **手感沉重** | 快速下落(fall multiplier),跳跃顶点缓降 |
|
||||
| **容错空间** | 土狼时间、跳跃缓冲降低输入失误惩罚 |
|
||||
| **进阶可深** | 空中冲刺+墙跳的组合技深度 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 地面移动
|
||||
|
||||
### 2.1 水平移动
|
||||
|
||||
| 状态 | 速度 | 说明 |
|
||||
|------|------|------|
|
||||
| 行走(轻推摇杆)| `walkSpeed` | 6 units/s |
|
||||
| 奔跑(全推摇杆)| `runSpeed` | 9 units/s |
|
||||
|
||||
- 水平速度**即时响应**输入,无加速/减速惯性
|
||||
- 松开输入时立即停止(不滑行)
|
||||
|
||||
> **设计决策**:不使用加速/减速曲线
|
||||
> **原因**:类银河恶魔城强调精确跳台,惯性会使平台跳跃难以预判落点
|
||||
|
||||
### 2.2 朝向
|
||||
|
||||
- 朝向随水平输入即时翻转
|
||||
- 攻击/技能状态中锁定朝向(不随输入改变)
|
||||
|
||||
---
|
||||
|
||||
## 3. 跳跃模型
|
||||
|
||||
### 3.1 跳跃类型
|
||||
|
||||
| 类型 | 触发条件 | 初速度 | 备注 |
|
||||
|------|---------|--------|------|
|
||||
| 地面跳跃 | 地面 + 跳跃键 | `jumpForce` | 标准跳跃 |
|
||||
| 土狼跳 | 离地后 `coyoteTime` 内 + 跳跃键 | `jumpForce` | 视为地面跳跃 |
|
||||
| 双跳 | 空中 + 跳跃键 + `DoubleJump` 已解锁 + 未使用过 | `doubleJumpForce` | 每次落地重置 |
|
||||
| 墙跳(背墙)| 贴墙 + 跳跃键 | 水平: `wallJumpAwayHForce`,垂直: `wallJumpVerticalForce` | 背离墙壁方向 |
|
||||
| 墙跳(对墙)| 贴墙 + 朝墙方向 + 跳跃键 | 水平: `wallJumpTowardHForce`,垂直: `wallJumpVerticalForce` | 朝墙壁方向 |
|
||||
|
||||
### 3.2 可变跳跃高度
|
||||
|
||||
松开跳跃键时,若玩家垂直速度仍向上,截断为原值的 50%。
|
||||
→ 长按获得完整跳跃高度;短按获得约一半高度。
|
||||
|
||||
### 3.3 重力模型
|
||||
|
||||
使用**非对称重力**以获得"果断"手感:
|
||||
|
||||
| 阶段 | 重力倍率 |
|
||||
|------|---------|
|
||||
| 上升阶段 | ×1.0(基础重力)|
|
||||
| 下落阶段 | ×`fallMultiplier`(默认 2.5)|
|
||||
| 短跳(松键后上升)| ×`lowJumpMultiplier`(默认 2.0)|
|
||||
| 跳跃顶点(速度接近 0)| 短暂降低至 ×0.6(缓降感)|
|
||||
|
||||
### 3.4 跳跃缓冲(Jump Buffer)
|
||||
|
||||
在落地前 `jumpBufferDuration`(默认 0.15s)内按下跳跃键,落地后立即触发跳跃。
|
||||
→ 消除玩家"刚好落地后跳跃失败"的挫败感。
|
||||
|
||||
---
|
||||
|
||||
## 4. 冲刺系统
|
||||
|
||||
### 4.1 地面冲刺
|
||||
|
||||
| 参数 | 值 | 说明 |
|
||||
|------|-----|------|
|
||||
| 方向 | 当前朝向(水平,不可向上/下)| 地面冲刺只能水平 |
|
||||
| 速度 | `dashSpeed` (18 units/s) | 远高于跑步速度 |
|
||||
| 时长 | `dashDuration` (0.18s) | 固定时长 |
|
||||
| 冷却 | `dashCooldown` (0.5s) | 冷却期间不可再冲刺 |
|
||||
| 无敌帧 | 冲刺全程 | 不受任何伤害 |
|
||||
| 穿透 | 可穿过敌人 | 不被敌人阻挡 |
|
||||
|
||||
### 4.2 冲刺取消
|
||||
|
||||
冲刺中不可被低优先级状态打断。但以下情况可中断:
|
||||
- 受到 `Unblockable` 攻击(仅此一项,普通攻击在冲刺无敌期间被忽略)
|
||||
|
||||
---
|
||||
|
||||
## 5. 墙壁力学
|
||||
|
||||
### 5.1 墙抓(WallGrab)
|
||||
|
||||
> **默认解锁**,不需要能力门
|
||||
|
||||
当玩家在空中贴近可抓取的墙壁并输入朝墙方向时,进入 WallGrabState:
|
||||
|
||||
| 行为 | 说明 |
|
||||
|------|------|
|
||||
| 悬挂 | 玩家停止下落,附着在墙上 |
|
||||
| 高度记忆 | 记录抓墙时的 Y 坐标(`wallGrabAnchorY`)|
|
||||
| 超出记忆值 | 玩家可向上爬(无上限)|
|
||||
| 低于记忆值 | 按 `wallGrabSlideSpeed` 缓慢下滑(不快速下落)|
|
||||
| 持续时间 | 无时间限制(可一直抓)|
|
||||
|
||||
### 5.2 墙跳类型
|
||||
|
||||
| 类型 | 触发 | 水平冲力 | 垂直冲力 |
|
||||
|------|------|---------|---------|
|
||||
| **背墙跳** | 跳跃键(无方向或反向)| `wallJumpAwayHForce` (10) | `wallJumpVerticalForce` (15) |
|
||||
| **对墙跳** | 朝墙方向 + 跳跃键 | `wallJumpTowardHForce` (3) | `wallJumpVerticalForce` (15) |
|
||||
|
||||
背墙跳弹离效果强,用于快速脱离;对墙跳爬升效果强,用于沿墙向上攀爬。
|
||||
|
||||
> **设计决策**:两种墙跳共用垂直分量
|
||||
> **原因**:统一手感基准,区别仅在水平表现
|
||||
|
||||
### 5.3 墙跳后的输入锁定
|
||||
|
||||
背墙跳后:
|
||||
- 水平方向输入锁定 0.1s(防止玩家立即贴回同一面墙)
|
||||
|
||||
---
|
||||
|
||||
## 6. 空中冲刺(Aerial Dash)
|
||||
|
||||
> **需要解锁** `AerialDash` 能力
|
||||
|
||||
### 6.1 基本规则
|
||||
|
||||
| 参数 | 值 | 说明 |
|
||||
|------|-----|------|
|
||||
| 方向 | 8 方向(摇杆方向量化)| 与地面冲刺最大区别 |
|
||||
| 速度 | `aerialDashSpeed` (15 units/s) | 略低于地面冲刺 |
|
||||
| 时长 | `aerialDashDuration` (0.20s) | |
|
||||
| 无敌帧 | 冲刺全程 | 同地面冲刺 |
|
||||
| 充能次数 | 默认 1 次(护符可升至 2 次)| 每次空中各自独立 |
|
||||
|
||||
### 6.2 充能重置条件
|
||||
|
||||
| 触发条件 | 说明 |
|
||||
|---------|------|
|
||||
| 落地 | 触地瞬间恢复 |
|
||||
| 墙跳成功 | 墙跳给予新的空中冲刺机会 |
|
||||
| **近战攻击命中** | 命中敌人即恢复(鼓励进攻性空中移动)|
|
||||
| **弹反成功** | 弹反视为命中,给予恢复 |
|
||||
|
||||
> **设计决策**:命中恢复充能
|
||||
> **原因**:这是《丝之歌》核心机制,使得玩家可以通过激进攻击保持永续空中移动。
|
||||
> **体验目标**:顶级玩家应该能通过攻击和弹反的组合在空中无限机动。
|
||||
|
||||
### 6.3 方向量化规则
|
||||
|
||||
摇杆输入方向量化为 8 个标准方向(45° 间隔):
|
||||
- 上/下/左/右(4 个主方向)
|
||||
- 左上/右上/左下/右下(4 个斜方向)
|
||||
- 若无输入,默认朝当前朝向水平冲刺
|
||||
|
||||
---
|
||||
|
||||
## 7. 下冲(Plunge)
|
||||
|
||||
> **无需解锁**,基础能力
|
||||
|
||||
### 7.1 触发条件
|
||||
|
||||
```
|
||||
空中 + 向下方向输入 + 冲刺键
|
||||
(优先级高于普通空中冲刺)
|
||||
```
|
||||
|
||||
### 7.2 行为规范
|
||||
|
||||
| 阶段 | 说明 |
|
||||
|------|------|
|
||||
| 激活 | 取消垂直速度,施加极大向下速度(`plungeSpeed` = 28 units/s)|
|
||||
| 下冲中 | 全程无敌帧;保留少量水平速度(原值 ×0.2)|
|
||||
| 落地 | 触发冲击波 AoE,范围内敌人受伤 + 强硬直 |
|
||||
| 落地后 | 轻微弹起(`verticalBounce` = 4 units/s)→ 回 IdleState |
|
||||
| 充能消耗 | 消耗 1 次空中冲刺充能(与 AerialDash 共享)|
|
||||
|
||||
### 7.3 冲击波参数
|
||||
|
||||
| 参数 | 值 |
|
||||
|------|-----|
|
||||
| 冲击波半径 | 2.0 units |
|
||||
| 冲击伤害 | 基础攻击 ×2.0 |
|
||||
| 硬直时长 | 0.8s |
|
||||
| 是否可弹反 | 否 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 地面与碰撞检测
|
||||
|
||||
### 8.1 地面检测
|
||||
|
||||
- 在角色脚部发起**小矩形区域检测**,检测 Ground 层
|
||||
- 每帧更新,检测结果对外暴露为只读属性 `isGrounded`
|
||||
- **单向平台**(OneWayPlatform):
|
||||
- 从下方跳跃时穿过(检测忽略该层)
|
||||
- 站在上方时视为地面
|
||||
- 向下 + 跳跃键:临时忽略单向平台层,允许下穿
|
||||
|
||||
### 8.2 土狼时间(Coyote Time)
|
||||
|
||||
离开地面后(如走出平台边缘)的 `coyoteTime`(默认 0.12s)内仍视为"在地面":
|
||||
- 这段时间内可触发地面跳跃
|
||||
- 只对自然离地有效(跳跃后不产生土狼时间)
|
||||
|
||||
### 8.3 墙壁检测
|
||||
|
||||
- 在角色左右两侧各发出一条水平射线
|
||||
- 检测 Wall 层
|
||||
- 结果:`isWallLeft` / `isWallRight`
|
||||
- 区分"可抓墙"和"不可抓墙"(通过墙壁属性标记)
|
||||
|
||||
---
|
||||
|
||||
## 9. 移动配置参数
|
||||
|
||||
| 参数 | 推荐值 | 说明 |
|
||||
|------|--------|------|
|
||||
| `walkSpeed` | 6.0 | 地面行走速度(units/s)|
|
||||
| `runSpeed` | 9.0 | 地面奔跑速度(units/s)|
|
||||
| `jumpForce` | 16.0 | 跳跃初始垂直速度 |
|
||||
| `doubleJumpForce` | 14.0 | 双跳初始垂直速度 |
|
||||
| `wallJumpAwayHForce` | 10.0 | 背墙跳水平分量 |
|
||||
| `wallJumpTowardHForce` | 3.0 | 对墙跳水平分量 |
|
||||
| `wallJumpVerticalForce` | 15.0 | 墙跳垂直分量 |
|
||||
| `wallJumpInputLockDuration` | 0.1s | 背墙跳后水平输入锁定时长 |
|
||||
| `wallGrabSlideSpeed` | 2.0 | 抓墙下滑速度(低于记忆高度时)|
|
||||
| `dashSpeed` | 18.0 | 地面冲刺速度 |
|
||||
| `dashDuration` | 0.18s | 地面冲刺时长 |
|
||||
| `dashCooldown` | 0.5s | 冲刺冷却时间 |
|
||||
| `aerialDashSpeed` | 15.0 | 空中冲刺速度 |
|
||||
| `aerialDashDuration` | 0.20s | 空中冲刺时长 |
|
||||
| `plungeSpeed` | 28.0 | 下冲速度 |
|
||||
| `plungeImpactRadius` | 2.0 | 下冲冲击波半径 |
|
||||
| `plungeBounceForce` | 4.0 | 落地后弹起速度 |
|
||||
| `fallMultiplier` | 2.5 | 下落额外重力倍率 |
|
||||
| `lowJumpMultiplier` | 2.0 | 短跳额外重力倍率 |
|
||||
| `apexGravityScale` | 0.6 | 跳跃顶点重力缩减倍率 |
|
||||
| `coyoteTimeDuration` | 0.12s | 土狼时间窗口 |
|
||||
| `jumpBufferDuration` | 0.15s | 跳跃预输入缓冲窗口 |
|
||||
| `groundCheckSize` | (0.8, 0.05) | 地面检测矩形尺寸 |
|
||||
| `wallCheckDistance` | 0.1 | 墙壁检测射线长度 |
|
||||
232
Docs/DesignSpec/06_FormSystem.md
Normal file
232
Docs/DesignSpec/06_FormSystem.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# 06 · 形态系统规范
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:三形态(天魂/地魂/命魂)的数据模型、切换契约、武器适配与技能体系。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [形态设计目标](#1-形态设计目标)
|
||||
2. [形态数据模型](#2-形态数据模型)
|
||||
3. [形态切换契约](#3-形态切换契约)
|
||||
4. [三形态规格表](#4-三形态规格表)
|
||||
5. [技能体系](#5-技能体系)
|
||||
6. [武器与形态联动](#6-武器与形态联动)
|
||||
7. [形态配置参数](#7-形态配置参数)
|
||||
|
||||
---
|
||||
|
||||
## 1. 形态设计目标
|
||||
|
||||
| 目标 | 说明 |
|
||||
|------|------|
|
||||
| **风格差异化** | 三形态提供截然不同的战斗体验,不仅仅是皮肤替换 |
|
||||
| **情境适应** | 不同区域/敌人类型鼓励不同形态,但不强制 |
|
||||
| **无缝切换** | 切换不中断当前动作,下次输入时生效 |
|
||||
| **可扩展** | 新增形态只需新增数据,不需要修改现有逻辑 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 形态数据模型
|
||||
|
||||
```
|
||||
DataModel FormData {
|
||||
formId : ID // 形态唯一标识(如 "SkyForm")
|
||||
displayName : String // 显示名称("天魂")
|
||||
description : String // 一句话描述
|
||||
accentColor : Color // HUD/特效色调
|
||||
──────────────────────────────────
|
||||
defaultWeapon : Ref<WeaponData> // 默认武器(连击动画+伤害来源+判定尺寸)
|
||||
soulSkill : Ref<SkillData> // 魂技能(消耗灵力)
|
||||
spiritSkill1 : Ref<SkillData> // 魄技能 1(消耗魄元)
|
||||
spiritSkill2 : Ref<SkillData> // 魄技能 2(消耗魄元)
|
||||
──────────────────────────────────
|
||||
switchAnimation : Optional<AnimationID> // 切换前摇动画(无则立即切换)
|
||||
unlockCondition : Optional<Ref<AbilityData>> // 解锁条件(null=初始可用)
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
DataModel WeaponData {
|
||||
weaponId : ID
|
||||
formId : ID // 归属形态
|
||||
──────────────────────────────────
|
||||
attack1Anim : AnimationID // 第一击动画
|
||||
attack2Anim : AnimationID // 第二击动画
|
||||
attack3Anim : AnimationID // 第三击动画
|
||||
airAttackAnim : AnimationID
|
||||
upAttackAnim : AnimationID
|
||||
downAttackAnim : AnimationID
|
||||
──────────────────────────────────
|
||||
hitBoxConfig : List<HitBoxSpec> // 各攻击段的判定区域规格
|
||||
damageMultipliers: Map<AttackType, Number> // 各攻击段伤害倍率
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 形态切换契约
|
||||
|
||||
### 3.1 切换输入映射
|
||||
|
||||
| 输入槽 | 默认形态 | 说明 |
|
||||
|--------|---------|------|
|
||||
| 槽位 0 | 天魂(SkyForm)| 键位 1 / 手柄方向键左 |
|
||||
| 槽位 1 | 地魂(EarthForm)| 键位 2 / 手柄方向键下 |
|
||||
| 槽位 2 | 命魂(DeathForm)| 键位 3 / 手柄方向键右 |
|
||||
|
||||
> **设计决策**:使用有序槽位而非形态枚举
|
||||
> **原因**:未来新增第四形态时,只需增加新输入槽和新 FormData,不改变现有逻辑
|
||||
|
||||
### 3.2 切换时机
|
||||
|
||||
```
|
||||
玩家按下形态切换键
|
||||
→ 目标形态 = 对应槽位的 FormData
|
||||
|
||||
目标形态 == 当前形态?
|
||||
├─ 是 → 忽略输入
|
||||
└─ 否 →
|
||||
|
||||
目标形态有切换前摇动画?
|
||||
├─ 是 → 播放前摇,前摇完成后切换
|
||||
└─ 否 → **立即** 更新 CurrentForm(不中断当前动作)
|
||||
|
||||
→ 发出 OnFormChanged 事件(传入新 FormData)
|
||||
→ WeaponSlot 接收事件,自动切换为新形态的默认武器
|
||||
→ 下次攻击/技能输入时,使用新形态的动画和参数
|
||||
```
|
||||
|
||||
### 3.3 切换的"无缝"原则
|
||||
|
||||
- 切换**本身无前摇**(默认配置下)
|
||||
- 当前动作(如攻击、冲刺)**不被打断**
|
||||
- 下一次攻击输入才体现新形态效果
|
||||
- 技能(魂技能/魄技能)绑定于形态,切换后技能槽内容随之改变
|
||||
|
||||
---
|
||||
|
||||
## 4. 三形态规格表
|
||||
|
||||
### 4.1 天魂形态(SkyForm)
|
||||
|
||||
| 属性 | 规格 |
|
||||
|------|------|
|
||||
| 战斗风格 | 轻快连击,空中机动性强 |
|
||||
| 攻击判定 | 较小范围,近身贴脸 |
|
||||
| 连击特点 | 第三击向上抛起敌人 |
|
||||
| 魂技能 | **天光斩**:前冲斩击,穿透多个敌人,灵力消耗 100 |
|
||||
| 魄技能 1 | **天翔步**:瞬间向上跳跃(额外跳),魄元消耗 40 |
|
||||
| 魄技能 2 | **灵鸟护体**:短暂无敌 + 反伤护盾,魄元消耗 70 |
|
||||
| 定位 | 灵活流,擅长空中平台战斗 |
|
||||
|
||||
### 4.2 地魂形态(EarthForm)
|
||||
|
||||
| 属性 | 规格 |
|
||||
|------|------|
|
||||
| 战斗风格 | 重击范围大,霸体强 |
|
||||
| 攻击判定 | 较大范围,有前置停顿 |
|
||||
| 连击特点 | 第三击震地,范围伤害 |
|
||||
| 魂技能 | **大地震怒**:跳起落下产生冲击波,灵力消耗 100 |
|
||||
| 魄技能 1 | **岩甲护卫**:护盾层(吸收 X 点伤害),魄元消耗 50 |
|
||||
| 魄技能 2 | **地裂踏**:踏地减速附近敌人,魄元消耗 60 |
|
||||
| 定位 | 坦克流,擅长对峙 Boss 和密集敌人 |
|
||||
|
||||
### 4.3 命魂形态(DeathForm)
|
||||
|
||||
| 属性 | 规格 |
|
||||
|------|------|
|
||||
| 战斗风格 | 中等速度,弹反增益显著 |
|
||||
| 攻击判定 | 适中范围,攻击后有追加效果 |
|
||||
| 连击特点 | 每击命中后留下诅咒标记,第三击引爆全部标记 |
|
||||
| 魂技能 | **命魂索链**:召唤锁链束缚最近敌人,灵力消耗 100 |
|
||||
| 魄技能 1 | **命魂反噬**:下次弹反触发额外爆炸伤害,魄元消耗 45 |
|
||||
| 魄技能 2 | **命域领域**:短暂降低附近敌人攻击力,魄元消耗 65 |
|
||||
| 定位 | 弹反流,弹反策略强化,适合精通玩家 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 技能体系
|
||||
|
||||
### 5.1 技能数据模型
|
||||
|
||||
```
|
||||
DataModel SkillData {
|
||||
skillId : ID
|
||||
skillName : String
|
||||
description : String
|
||||
resourceType : ResourceType // SoulPower 或 SpiritPower
|
||||
resourceCost : Integer // 消耗量
|
||||
──────────────────────────────────
|
||||
castAnimation : AnimationID // 前摇动画
|
||||
castDuration : Duration // 前摇时长
|
||||
effectDelay : Duration // 前摇结束后效果开始的延迟
|
||||
──────────────────────────────────
|
||||
effectType : SkillEffectType
|
||||
effectParams : Map<String, Number> // 效果参数(因技能类型而异)
|
||||
──────────────────────────────────
|
||||
canCastAirborne : Boolean // 是否可在空中施放
|
||||
interruptible : Boolean // 前摇是否可被打断(冲刺/受伤仍可打断)
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 技能效果类型
|
||||
|
||||
| 类型 | 说明 | 典型参数 |
|
||||
|------|------|---------|
|
||||
| `Projectile` | 发射弹射物 | `speed`, `damage`, `piercing` |
|
||||
| `Melee` | 近战范围攻击 | `radius`, `damage`, `knockback` |
|
||||
| `Shield` | 护盾效果 | `absorbAmount`, `duration` |
|
||||
| `Buff` | 正面增益 | `buffType`, `duration`, `magnitude` |
|
||||
| `Debuff` | 负面施加 | `debuffType`, `duration`, `radius` |
|
||||
| `Summon` | 召唤实体 | `entityId`, `duration`, `count` |
|
||||
| `Mobility` | 移动型技能 | `distance`, `direction`, `invincible` |
|
||||
|
||||
### 5.3 资源消耗规则
|
||||
|
||||
| 资源类型 | 消耗时机 | 失败处理 |
|
||||
|---------|---------|---------|
|
||||
| 灵力 | 技能执行前检查,通过则立即扣除 | 不足时技能键无响应 |
|
||||
| 魄元 | 技能执行前检查,通过则立即扣除 | 不足时技能键无响应 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 武器与形态联动
|
||||
|
||||
### 6.1 武器切换流程
|
||||
|
||||
```
|
||||
OnFormChanged 事件触发
|
||||
→ WeaponSlot 更新为新形态的 defaultWeapon
|
||||
→ CombatHandler 刷新以下内容:
|
||||
├─ 当前连击段的动画片段
|
||||
├─ HitArea 尺寸与偏移
|
||||
├─ DamagePacket 中的伤害倍率来源
|
||||
└─ 重置连击计数器(ComboState → None)
|
||||
```
|
||||
|
||||
### 6.2 护符武器覆盖
|
||||
|
||||
特定护符可覆盖某形态的默认武器(只改变该形态):
|
||||
- 护符持有 `WeaponData` 引用
|
||||
- 装备时:对应槽位的 `FormData.defaultWeapon` 临时被护符武器替代
|
||||
- 卸装时:恢复原 `FormData.defaultWeapon`
|
||||
|
||||
---
|
||||
|
||||
## 7. 形态配置参数
|
||||
|
||||
| 参数 | 说明 |
|
||||
|------|------|
|
||||
| 三形态 FormData | 见第 4 节规格表 |
|
||||
| 各形态武器 HitBox 尺寸 | 在各 WeaponData 中配置 |
|
||||
| 技能消耗量 | 在各 SkillData 中配置 |
|
||||
| 技能前摇时长 | 在各 SkillData 中配置 |
|
||||
|
||||
> **扩展原则**:新增形态时,只需:
|
||||
> 1. 创建新的 `FormData`(含武器和技能引用)
|
||||
> 2. 将其加入形态配置列表的新槽位
|
||||
> 3. 为新槽位绑定输入键位
|
||||
>
|
||||
> 无需修改任何现有系统逻辑。
|
||||
289
Docs/DesignSpec/07_EnemySystem.md
Normal file
289
Docs/DesignSpec/07_EnemySystem.md
Normal file
@@ -0,0 +1,289 @@
|
||||
# 07 · 敌人系统规范
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:敌人实体模型、AI 行为规范、Boss 系统设计与掉落体系。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [设计原则](#1-设计原则)
|
||||
2. [敌人实体模型](#2-敌人实体模型)
|
||||
3. [AI 行为规范](#3-ai-行为规范)
|
||||
4. [寻路与感知](#4-寻路与感知)
|
||||
5. [Boss 系统](#5-boss-系统)
|
||||
6. [电报系统(攻击预警)](#6-电报系统攻击预警)
|
||||
7. [敌人分级体系](#7-敌人分级体系)
|
||||
8. [掉落系统](#8-掉落系统)
|
||||
|
||||
---
|
||||
|
||||
## 1. 设计原则
|
||||
|
||||
| 原则 | 说明 |
|
||||
|------|------|
|
||||
| **可读性优先** | 每个攻击都有明确的预警(电报),让玩家有机会反应 |
|
||||
| **弹反友好** | 大多数攻击标记为可弹反,鼓励玩家使用核心机制 |
|
||||
| **行为数据化** | AI 行为通过数据配置组合,不硬编码 |
|
||||
| **职责分离** | 移动、攻击、感知各为独立模块,互不依赖 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 敌人实体模型
|
||||
|
||||
### 2.1 实体构成
|
||||
|
||||
```
|
||||
EnemyEntity(协调器)
|
||||
├── EnemyStats ← 属性(HP、防御、速度等)
|
||||
├── AIController ← 行为决策(BehaviorTree 或 FSM)
|
||||
├── MovementAgent ← 路径跟随与物理移动
|
||||
├── CombatModule ← 攻击执行、HitArea 管理
|
||||
├── HurtBox ← 受击响应
|
||||
├── PerceptionModule ← 感知(视野、听觉、自定义触发器)
|
||||
├── LootModule ← 死亡掉落处理
|
||||
└── TelegraphSystem ← 攻击电报(预警视觉效果)
|
||||
```
|
||||
|
||||
### 2.2 敌人属性模型
|
||||
|
||||
```
|
||||
DataModel EnemyStatsData {
|
||||
enemyId : ID
|
||||
displayName : String
|
||||
──────────────────────────────────
|
||||
maxHP : Integer
|
||||
defense : Number // 伤害减免(0.0~1.0)
|
||||
poiseLevel : PoiseLevel // 霸体等级
|
||||
──────────────────────────────────
|
||||
moveSpeed : Number // 基础移动速度
|
||||
detectionRange : Number // 视野/感知范围
|
||||
attackRange : Number // 近战攻击范围
|
||||
──────────────────────────────────
|
||||
lootTableId : Ref<LootTableData> // 掉落表
|
||||
geoReward : {min: Integer, max: Integer} // Geo 掉落范围
|
||||
killCreditType : KillCreditType // 击杀积分类型(普通/精英/Boss)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. AI 行为规范
|
||||
|
||||
### 3.1 行为树节点类型
|
||||
|
||||
AI 行为通过**行为树(Behavior Tree)**组织,行为节点类型:
|
||||
|
||||
| 节点类型 | 符号 | 说明 |
|
||||
|---------|------|------|
|
||||
| 选择节点(Selector)| `?` | 依次尝试子节点,第一个成功即返回成功 |
|
||||
| 序列节点(Sequence)| `→` | 依次执行子节点,所有成功才返回成功 |
|
||||
| 条件节点(Condition)| `[C]` | 判断某个条件,返回成功/失败 |
|
||||
| 动作节点(Action)| `[A]` | 执行一个具体行为 |
|
||||
| 装饰节点(Decorator)| `{D}` | 修改子节点行为(如重复、反转、冷却)|
|
||||
|
||||
### 3.2 通用敌人行为树模板
|
||||
|
||||
```
|
||||
Root(Selector)
|
||||
├─ ? 死亡检测
|
||||
│ └─ [C] HP <= 0 → [A] 播放死亡动画 → [A] 触发掉落 → [A] 销毁
|
||||
│
|
||||
├─ ? 受击响应
|
||||
│ └─ [C] 正在受击 → [A] 受击动画(若霸体被打断)
|
||||
│
|
||||
├─ ? 攻击决策(Selector)
|
||||
│ ├─ ? 近战攻击
|
||||
│ │ └─ [C] 玩家在攻击范围内
|
||||
│ │ → [C] 攻击冷却结束
|
||||
│ │ → [A] 播放电报
|
||||
│ │ → [A] 执行攻击
|
||||
│ │
|
||||
│ └─ ? 远程攻击
|
||||
│ └─ [C] 玩家在视野内但超出近战范围
|
||||
│ → [C] 远程攻击冷却结束
|
||||
│ → [A] 播放电报
|
||||
│ → [A] 发射弹射物
|
||||
│
|
||||
├─ ? 追击(Sequence)
|
||||
│ ├─ [C] 已感知到玩家
|
||||
│ └─ [A] 向玩家移动(路径跟随)
|
||||
│
|
||||
└─ ? 巡逻/待机(Sequence)
|
||||
└─ [A] 执行巡逻路径(或原地待机)
|
||||
```
|
||||
|
||||
### 3.3 AI 感知状态
|
||||
|
||||
| 状态 | 条件 | 行为 |
|
||||
|------|------|------|
|
||||
| `Idle`(待机)| 未感知到玩家 | 巡逻或原地等待 |
|
||||
| `Alert`(警戒)| 听到声音或余光检测 | 转向检查,不主动追击 |
|
||||
| `Chase`(追击)| 视野内确认玩家 | 向玩家移动 |
|
||||
| `Combat`(战斗)| 玩家在攻击范围内 | 执行攻击序列 |
|
||||
| `Stunned`(硬直)| 受到重击/被弹反 | 暂停所有行为 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 寻路与感知
|
||||
|
||||
### 4.1 寻路规范
|
||||
|
||||
| 规范项 | 说明 |
|
||||
|--------|------|
|
||||
| 寻路类型 | 2D 导航网格(NavMesh)或路径点系统 |
|
||||
| 更新频率 | 目标位置变化超过阈值时重新规划路径(不每帧更新)|
|
||||
| 跳跃/下落 | 可配置是否允许跳跃/从平台下落追击 |
|
||||
| 障碍物 | 动态障碍物(其他敌人)不重新规划路径,简单规避 |
|
||||
|
||||
### 4.2 感知规范
|
||||
|
||||
```
|
||||
DataModel PerceptionConfig {
|
||||
visionRange : Number // 视野半径
|
||||
visionAngle : Number // 视野角度(正前方±角度)
|
||||
hearingRange : Number // 听觉半径(玩家移动/攻击触发)
|
||||
alertDuration : Duration // Alert 状态持续时长
|
||||
lostTargetDelay : Duration // 失去视野到放弃追击的延迟
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Boss 系统
|
||||
|
||||
### 5.1 Boss 实体模型
|
||||
|
||||
Boss 继承普通敌人的所有能力,附加以下扩展:
|
||||
|
||||
```
|
||||
DataModel BossData extends EnemyStatsData {
|
||||
bossName : String
|
||||
arenaId : ID // 专属战斗场景
|
||||
──────────────────────────────────────
|
||||
phases : List<BossPhaseData> // 阶段列表(按顺序触发)
|
||||
introSequenceId : ID // 入场演出序列
|
||||
defeatSequenceId: ID // 失败演出序列
|
||||
──────────────────────────────────────
|
||||
bgmPhase1 : AudioID
|
||||
bgmPhase2 : Optional<AudioID> // 阶段变更时切换音乐
|
||||
}
|
||||
|
||||
DataModel BossPhaseData {
|
||||
phaseIndex : Integer
|
||||
hpThreshold : Number // 触发阶段变更的 HP 百分比(0~1.0)
|
||||
availableAttacks: List<Ref<AttackPatternData>> // 该阶段可用攻击
|
||||
attackWeights : Map<ID, Number> // 各攻击的选取权重
|
||||
aggressionScale : Number // 攻击频率倍率
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 Boss 攻击模式模型
|
||||
|
||||
```
|
||||
DataModel AttackPatternData {
|
||||
patternId : ID
|
||||
patternName : String
|
||||
──────────────────────────────
|
||||
telegraphType : TelegraphType // 电报类型
|
||||
telegraphDuration: Duration // 电报持续时间
|
||||
──────────────────────────────
|
||||
attackType : BossAttackType // 攻击类型
|
||||
executionParams : Map<String, Number> // 执行参数
|
||||
cooldown : Duration // 攻击后冷却
|
||||
──────────────────────────────
|
||||
isParryable : Boolean // 是否可被玩家弹反
|
||||
counterWindowId : Optional<ID> // 弹反后的脆弱窗口
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 Boss 阶段转换流程
|
||||
|
||||
```
|
||||
Boss HP 降至 PhaseData.hpThreshold 以下
|
||||
→ AIController 暂停(短暂无敌帧 0.5s)
|
||||
→ 播放相变动画/特效
|
||||
→ 发出 OnBossPhaseChanged 事件(bossId, newPhase)
|
||||
→ 更新可用攻击列表和攻击权重
|
||||
→ 音频系统切换音乐(若配置了 bgmPhase2)
|
||||
→ 恢复 AIController
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 电报系统(攻击预警)
|
||||
|
||||
所有攻击**必须**有电报,给玩家反应时间:
|
||||
|
||||
| 电报类型 | 视觉表现 | 适用场景 |
|
||||
|---------|---------|---------|
|
||||
| `PoseHold` | 攻击前摇姿势定格 | 近战重击 |
|
||||
| `GroundIndicator` | 地面出现警告范围标记 | 落地冲击、AoE |
|
||||
| `TrajectoryLine` | 显示弹射物飞行路径 | 精准弹射物 |
|
||||
| `BodyGlow` | 敌人身体特定颜色发光 | 不可弹反:红色;可弹反:黄色 |
|
||||
| `SoundCue` | 特定音效(与视觉结合)| 所有攻击必备 |
|
||||
|
||||
### 电报颜色规范
|
||||
|
||||
| 颜色 | 含义 |
|
||||
|------|------|
|
||||
| 黄色/金色 | 可弹反攻击 |
|
||||
| 红色/橙色 | 不可弹反攻击 |
|
||||
| 紫色 | 特殊/Boss 专属机制 |
|
||||
| 白色 | 环境危险(非敌人攻击)|
|
||||
|
||||
---
|
||||
|
||||
## 7. 敌人分级体系
|
||||
|
||||
| 等级 | 名称 | AI 复杂度 | 霸体 | 典型特征 |
|
||||
|------|------|----------|------|---------|
|
||||
| T1 | 杂兵 | 简单(2-3种行为)| Fragile | 单一攻击,跑向玩家 |
|
||||
| T2 | 普通敌人 | 中等(3-5种行为)| Standard | 有攻击组合,有简单规避 |
|
||||
| T3 | 精英怪 | 较高(5-7种行为)| Armored | 有阶段变化,有独特机制 |
|
||||
| T4 | Boss | 高(多阶段完整AI)| Boss | 多阶段、多攻击、电报复杂 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 掉落系统
|
||||
|
||||
### 8.1 掉落表模型
|
||||
|
||||
```
|
||||
DataModel LootTableData {
|
||||
tableId : ID
|
||||
entries : List<LootEntry>
|
||||
guaranteedDrops : List<Ref<ItemData>> // 必掉物品(如 Boss 必掉能力道具)
|
||||
}
|
||||
|
||||
DataModel LootEntry {
|
||||
itemId : Ref<ItemData>
|
||||
baseWeight : Number // 基础权重(相对概率)
|
||||
minCount : Integer
|
||||
maxCount : Integer
|
||||
difficultyScale : Number // 难度缩放系数(Easy 减少,Hard 增加)
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2 掉落概率计算
|
||||
|
||||
```
|
||||
各 Entry 的实际权重 = baseWeight × 难度系数
|
||||
总权重 = 所有 Entry 实际权重之和
|
||||
某 Entry 概率 = 该 Entry 实际权重 / 总权重
|
||||
|
||||
保底机制:
|
||||
若稀有物品连续 20 次未掉落 → 下次强制掉落
|
||||
保底计数存入 SaveData,跨死亡保留
|
||||
```
|
||||
|
||||
### 8.3 掉落触发流程
|
||||
|
||||
```
|
||||
OnEnemyDied 事件触发
|
||||
→ 掉落系统读取死亡敌人的 LootTableData
|
||||
→ 计算本次掉落结果(权重随机 + 保底检查)
|
||||
→ 在死亡位置生成掉落物实体
|
||||
→ Geo 直接加入玩家账户(不生成实体,减少拾取摩擦)
|
||||
→ 特殊道具生成拾取实体,玩家走近自动拾取
|
||||
```
|
||||
272
Docs/DesignSpec/08_WorldSystem.md
Normal file
272
Docs/DesignSpec/08_WorldSystem.md
Normal file
@@ -0,0 +1,272 @@
|
||||
# 08 · 世界系统规范
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:地图结构、房间系统、场景切换管线、存档点与可交互物。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [世界结构层级](#1-世界结构层级)
|
||||
2. [世界数据模型](#2-世界数据模型)
|
||||
3. [场景切换管线](#3-场景切换管线)
|
||||
4. [存档点系统](#4-存档点系统)
|
||||
5. [可交互物规范](#5-可交互物规范)
|
||||
6. [收集品系统](#6-收集品系统)
|
||||
7. [世界状态事件目录](#7-世界状态事件目录)
|
||||
|
||||
---
|
||||
|
||||
## 1. 世界结构层级
|
||||
|
||||
```
|
||||
World(全局)
|
||||
└── Region(区域,如 废墟之都 / 灵泉洞窟)
|
||||
└── Zone(地区,区域内的子区域)
|
||||
└── Room(房间,最小加载单元)
|
||||
└── Sector(区块,房间内的逻辑分区)
|
||||
```
|
||||
|
||||
| 层级 | 说明 | 数量(预期)|
|
||||
|------|------|-----------|
|
||||
| World | 整个游戏世界 | 1 |
|
||||
| Region | 玩家感知的"大区",通常有独特视觉主题 | 5-8 |
|
||||
| Zone | Region 内的子区域,对玩家透明(内部分组)| 20-30 |
|
||||
| Room | 场景加载单元,对应单个可加载场景文件 | 100-200 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 世界数据模型
|
||||
|
||||
### 2.1 地区(Region)数据
|
||||
|
||||
```
|
||||
DataModel RegionData {
|
||||
regionId : ID
|
||||
displayName : String
|
||||
description : String
|
||||
──────────────────────────────────
|
||||
ambientAudioId : AudioID // 区域环境音乐
|
||||
visualTheme : Ref<VisualThemeData> // 色调/视觉风格
|
||||
──────────────────────────────────
|
||||
rooms : List<Ref<RoomData>> // 该区域包含的所有房间
|
||||
connections : List<RegionConnection> // 与其他区域的连接
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 房间(Room)数据
|
||||
|
||||
```
|
||||
DataModel RoomData {
|
||||
roomId : ID
|
||||
regionId : ID // 归属区域
|
||||
──────────────────────────────────
|
||||
sceneAssetId : ID // 场景资源引用
|
||||
spawnPoints : Map<String, Vector2> // 命名生成点(对应门/入口的落地位置)
|
||||
──────────────────────────────────
|
||||
connections : List<RoomConnection> // 与其他房间的连接(门/通道)
|
||||
hasBoss : Boolean
|
||||
bossId : Optional<ID>
|
||||
──────────────────────────────────
|
||||
discoverable : Boolean // 是否出现在地图上
|
||||
mapGridPos : Vector2 // 在地图 UI 中的格位置
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 房间连接模型
|
||||
|
||||
```
|
||||
DataModel RoomConnection {
|
||||
fromRoomId : ID
|
||||
fromDoorId : String // 本房间出口标识
|
||||
toRoomId : ID
|
||||
toDoorId : String // 目标房间入口标识
|
||||
──────────────────────────────────
|
||||
direction : ConnectionDirection // 上/下/左/右
|
||||
gateId : Optional<ID> // 门控(null=无门限制)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 场景切换管线
|
||||
|
||||
### 3.1 切换触发条件
|
||||
|
||||
玩家进入出口触发器(Exit Trigger)时,触发场景切换流程:
|
||||
|
||||
```
|
||||
玩家进入 ExitTrigger
|
||||
→ 读取 RoomConnection(目标房间、目标入口)
|
||||
→ 检查门控条件(若有 gateId):
|
||||
├─ 未满足 → 门保持关闭,播放提示
|
||||
└─ 满足 → 继续流程
|
||||
|
||||
→ 发出 OnRoomTransitionBegin 事件
|
||||
→ 播放转场动画(淡出、卷帘等)
|
||||
→ 保存当前房间的必要运行时状态(敌人死亡/开关/收集品)
|
||||
→ 异步加载目标场景
|
||||
→ 等待加载完成
|
||||
→ 将玩家生成到目标房间的指定 spawnPoint
|
||||
→ 播放转场进入动画
|
||||
→ 发出 OnRoomTransitionComplete 事件(roomId)
|
||||
```
|
||||
|
||||
### 3.2 玩家状态保留
|
||||
|
||||
| 状态 | 切换时处理 |
|
||||
|------|-----------|
|
||||
| HP | 保留(不恢复)|
|
||||
| 灵力 | 保留 |
|
||||
| 魄元 | 保留 |
|
||||
| 灵泉 | 保留 |
|
||||
| 当前形态 | 保留 |
|
||||
| Geo | 保留 |
|
||||
| 无敌帧 | 清除 |
|
||||
| 速度/冲量 | 清除(生成时重置)|
|
||||
|
||||
### 3.3 房间状态持久化
|
||||
|
||||
| 状态类型 | 持久化条件 |
|
||||
|---------|----------|
|
||||
| 敌人死亡 | 永久(本局游戏内)|
|
||||
| 开关/机关激活 | 按道具/进程判断(大多数永久)|
|
||||
| 收集品拾取 | 永久 |
|
||||
| Boss 死亡 | 永久,切换不重置 |
|
||||
| 普通敌人死亡 | 重新进入房间后刷新 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 存档点系统
|
||||
|
||||
### 4.1 存档点数据模型
|
||||
|
||||
```
|
||||
DataModel BonfireData {
|
||||
bonfireId : ID
|
||||
roomId : ID
|
||||
position : Vector2
|
||||
──────────────────────────────────
|
||||
displayName : String
|
||||
isActivated : Boolean // 运行时状态,存入 SaveData
|
||||
fastTravelEnabled: Boolean // 是否支持快速旅行
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 激活流程
|
||||
|
||||
```
|
||||
玩家靠近存档点 → 显示交互提示
|
||||
玩家按下交互键:
|
||||
|
||||
若未激活:
|
||||
→ 播放激活动画
|
||||
→ 设置 BonfireData.isActivated = true
|
||||
→ 解锁快速旅行列表中该存档点
|
||||
|
||||
激活后(每次交互):
|
||||
→ 恢复玩家 HP 至最大值
|
||||
→ 恢复灵泉
|
||||
→ 重置敌人刷新状态(普通敌人复活)
|
||||
→ 保存游戏进度到 SaveData
|
||||
→ 发出 OnBonfireRested 事件
|
||||
```
|
||||
|
||||
> **设计决策**:存档点恢复灵泉
|
||||
> **原因**:灵泉是 HP 恢复资源,应随存档点恢复;但死亡后不恢复灵泉,强化死亡惩罚
|
||||
|
||||
### 4.3 死亡重生规则
|
||||
|
||||
- 死亡时:玩家重生于**最后一次使用的存档点**
|
||||
- 重生时:HP 恢复至最大值,**灵泉不恢复**
|
||||
- 玩家持有的 Geo 遗留在死亡位置(遗骸机制,见 [进程系统](09_ProgressionSystem.md))
|
||||
|
||||
---
|
||||
|
||||
## 5. 可交互物规范
|
||||
|
||||
### 5.1 交互契约
|
||||
|
||||
```
|
||||
Interface IInteractable {
|
||||
canInteract(player: IPlayerEntity) → Boolean
|
||||
onInteract(player: IPlayerEntity) → Void
|
||||
getPromptText() → String
|
||||
}
|
||||
```
|
||||
|
||||
所有可交互物实现此接口,由玩家系统负责检测并调用。
|
||||
|
||||
### 5.2 标准交互物类型
|
||||
|
||||
| 类型 | 触发条件 | 行为 |
|
||||
|------|---------|------|
|
||||
| 存档点(Bonfire)| 玩家靠近 + 按交互键 | 激活 / 休息 |
|
||||
| NPC | 玩家靠近 + 按交互键 | 开始对话(见叙事系统)|
|
||||
| 商店(Vendor)| 玩家靠近 + 按交互键 | 打开商店 UI |
|
||||
| 门(Gate)| 玩家靠近,满足条件自动开启 | 开启动画 + 移除碰撞 |
|
||||
| 传送门(Portal)| 玩家触碰 | 传送到目标地点 |
|
||||
| 机关(Mechanism)| 玩家靠近 + 按交互键 | 激活关联机关(开门/升降台)|
|
||||
| 收集品(Collectible)| 玩家触碰 / 按键 | 拾取(见收集品系统)|
|
||||
|
||||
---
|
||||
|
||||
## 6. 收集品系统
|
||||
|
||||
### 6.1 收集品数据模型
|
||||
|
||||
```
|
||||
DataModel CollectibleData {
|
||||
collectibleId : ID
|
||||
collectibleType : CollectibleType // 见下表
|
||||
roomId : ID // 所在房间
|
||||
──────────────────────────────────
|
||||
displayName : String
|
||||
description : String
|
||||
──────────────────────────────────
|
||||
pickupEffect : PickupEffectType // 拾取时发生什么
|
||||
pickupParams : Map<String, Number>
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 收集品类型
|
||||
|
||||
| 类型 | 说明 | 效果 |
|
||||
|------|------|------|
|
||||
| `MaxHPUp` | 生命上限增加 | `maxHP += pickupParams["amount"]` |
|
||||
| `MaxSoulUp` | 灵力上限增加 | `maxSoul += pickupParams["amount"]` |
|
||||
| `MaxSpiritUp` | 魄元上限增加 | `maxSpirit += pickupParams["amount"]` |
|
||||
| `AbilityUnlock` | 解锁新能力 | 发出 `OnAbilityUnlocked` 事件 |
|
||||
| `MapFragment` | 解锁区域地图 | 揭示对应区域地图 |
|
||||
| `Lore` | 世界观文本 | 加入图鉴/日志 |
|
||||
| `GeoCache` | 货币缓存 | 立即给予 Geo |
|
||||
|
||||
### 6.3 拾取流程
|
||||
|
||||
```
|
||||
玩家触碰 CollectibleEntity
|
||||
→ 检查 SaveData 该 collectibleId 是否已拾取
|
||||
├─ 已拾取 → 忽略(不重复拾取)
|
||||
└─ 未拾取 →
|
||||
→ 播放拾取动画/音效
|
||||
→ 执行 pickupEffect(更新玩家数据)
|
||||
→ 将 collectibleId 标记为已拾取(写入 SaveData)
|
||||
→ 发出 OnCollectiblePickedUp 事件
|
||||
→ 销毁实体(本局不再出现)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 世界状态事件目录
|
||||
|
||||
| 事件 | 触发时机 | 载荷 |
|
||||
|------|---------|------|
|
||||
| `OnRoomTransitionBegin` | 场景切换开始 | `fromRoomId, toRoomId` |
|
||||
| `OnRoomTransitionComplete` | 场景切换完成 | `roomId` |
|
||||
| `OnRoomFirstVisit` | 首次进入某房间 | `roomId` |
|
||||
| `OnBonfireActivated` | 首次激活存档点 | `bonfireId` |
|
||||
| `OnBonfireRested` | 使用存档点休息 | `bonfireId` |
|
||||
| `OnCollectiblePickedUp` | 拾取收集品 | `collectibleId, collectibleType` |
|
||||
| `OnGateOpened` | 门控解锁 | `gateId, roomId` |
|
||||
| `OnBossRoomEntered` | 进入 Boss 房间 | `roomId, bossId` |
|
||||
| `OnBossDefeated` | Boss 死亡 | `bossId` |
|
||||
246
Docs/DesignSpec/09_ProgressionSystem.md
Normal file
246
Docs/DesignSpec/09_ProgressionSystem.md
Normal file
@@ -0,0 +1,246 @@
|
||||
# 09 · 进程系统规范
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:能力解锁、门控系统、Geo 遗骸机制与游戏完成度追踪。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [进程设计原则](#1-进程设计原则)
|
||||
2. [能力系统](#2-能力系统)
|
||||
3. [门控系统](#3-门控系统)
|
||||
4. [Geo 遗骸机制](#4-geo-遗骸机制)
|
||||
5. [完成度追踪](#5-完成度追踪)
|
||||
6. [护符系统](#6-护符系统)
|
||||
7. [进程事件目录](#7-进程事件目录)
|
||||
|
||||
---
|
||||
|
||||
## 1. 进程设计原则
|
||||
|
||||
| 原则 | 说明 |
|
||||
|------|------|
|
||||
| **有机探索** | 能力解锁带来新的区域通路,而非仅仅提升战斗数值 |
|
||||
| **无死门** | 不存在因获取顺序错误而无法继续的情况 |
|
||||
| **多路径** | 大多数门控有多种解锁方式(能力/密钥/支线)|
|
||||
| **数据驱动** | 所有解锁条件用数据定义,逻辑层不硬编码 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 能力系统
|
||||
|
||||
### 2.1 能力数据模型
|
||||
|
||||
```
|
||||
DataModel AbilityData {
|
||||
abilityId : ID
|
||||
displayName : String
|
||||
description : String
|
||||
──────────────────────────────────
|
||||
abilityType : AbilityType // 移动/战斗/探索/形态
|
||||
unlockSource : UnlockSource // 如何获得(Boss掉落/收集品/商店)
|
||||
──────────────────────────────────
|
||||
gatesUnlocked : List<GateType> // 该能力解锁哪些门控类型
|
||||
movementFlags : Flags<MovementAbilityFlag> // 移动系统的能力开关
|
||||
combatFlags : Flags<CombatAbilityFlag> // 战斗系统的能力开关
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 核心能力列表
|
||||
|
||||
| 能力 ID | 名称 | 获取方式 | 解锁内容 |
|
||||
|--------|------|---------|---------|
|
||||
| `DoubleJump` | 双跳 | 初始能力(教程)| 空中二段跳 |
|
||||
| `WallGrab` | 墙抓 | 区域 1 Boss | 抓墙/墙跳 |
|
||||
| `AerialDash` | 空中冲刺 | 区域 2 Boss | 8方向空中冲刺 |
|
||||
| `Plunge` | 下冲 | 区域 3 收集品 | 下冲攻击 |
|
||||
| `SwimAbility` | 游泳 | 区域 4 收集品 | 进入液体区域 |
|
||||
| `SkyFormUnlock` | 天魂解锁 | 剧情节点 | 天魂形态 |
|
||||
| `EarthFormUnlock` | 地魂解锁 | 剧情节点 | 地魂形态 |
|
||||
| `DeathFormUnlock` | 命魂解锁 | 剧情节点 | 命魂形态 |
|
||||
| `SoulSkillUpgrade` | 魂技能升级 | 特定 NPC | 魂技能二阶效果 |
|
||||
|
||||
### 2.3 能力解锁流程
|
||||
|
||||
```
|
||||
玩家获得 AbilityData(来源:Boss掉落/拾取/购买)
|
||||
→ 发出 OnAbilityUnlocked 事件(abilityId)
|
||||
→ 更新 SaveData.unlockedAbilities 集合
|
||||
→ 玩家系统注册新 movementFlags 和 combatFlags
|
||||
→ 门控系统重新评估所有已知门控状态
|
||||
→ 地图更新(若新能力打开了新路径)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 门控系统
|
||||
|
||||
### 3.1 门控数据模型
|
||||
|
||||
```
|
||||
DataModel GateData {
|
||||
gateId : ID
|
||||
roomId : ID
|
||||
displayName : String
|
||||
──────────────────────────────────
|
||||
conditions : List<GateCondition> // 解锁条件(满足任一即可,OR逻辑)
|
||||
unlockMode : GateUnlockMode // 永久解锁 / 单次通过
|
||||
──────────────────────────────────
|
||||
lockedVisual : VisualState
|
||||
unlockedVisual : VisualState
|
||||
tooltipText : String // 玩家尝试进入未解锁门时显示
|
||||
}
|
||||
|
||||
DataModel GateCondition {
|
||||
conditionType : GateConditionType
|
||||
targetId : ID // 依条件类型:能力ID/密钥ID/任务ID
|
||||
quantity : Optional<Integer> // 若需要数量(如 Geo 消耗)
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 门控条件类型
|
||||
|
||||
| 条件类型 | 说明 | 示例 |
|
||||
|---------|------|------|
|
||||
| `HasAbility` | 玩家已解锁某能力 | 需要双跳才能通过高台 |
|
||||
| `HasItem` | 玩家持有某关键道具 | 需要古城钥匙 |
|
||||
| `BossDefeated` | 某 Boss 已被击败 | 区域终 Boss 死后大门开启 |
|
||||
| `QuestComplete` | 某任务/剧情已完成 | NPC 认可后打开秘道 |
|
||||
| `PaidGeo` | 支付 Geo(商人/通行税)| 进入特定区域收费 |
|
||||
| `WorldFlag` | 某世界标记为真 | 触发了某机关后解锁 |
|
||||
|
||||
---
|
||||
|
||||
## 4. Geo 遗骸机制
|
||||
|
||||
### 4.1 规则规范
|
||||
|
||||
```
|
||||
玩家死亡:
|
||||
→ 当前持有的 Geo 全部转移为遗骸(GeoShade)
|
||||
→ 遗骸实体生成于死亡位置
|
||||
→ 玩家的 Geo 归零
|
||||
→ 若已有遗骸(上一次死亡未取回):
|
||||
→ 旧遗骸永久消失(及其中的 Geo)
|
||||
→ 新遗骸替代旧遗骸
|
||||
|
||||
玩家到达遗骸位置并触碰:
|
||||
→ 恢复遗骸中的全部 Geo
|
||||
→ 遗骸消失
|
||||
→ 发出 OnGeoShadeRecovered 事件
|
||||
```
|
||||
|
||||
### 4.2 数据模型
|
||||
|
||||
```
|
||||
DataModel GeoShadeState {
|
||||
exists : Boolean
|
||||
geoAmount : Integer
|
||||
deathPosition : Vector2
|
||||
roomId : ID // 遗骸所在房间(跨房间持久存在)
|
||||
}
|
||||
```
|
||||
|
||||
> **设计决策**:再次死亡前遗骸永久消失
|
||||
> **原因**:来自 Hollow Knight 的核心惩罚机制。失去 Geo 的焦虑推动玩家谨慎前进,而非莽撞行事。
|
||||
|
||||
---
|
||||
|
||||
## 5. 完成度追踪
|
||||
|
||||
### 5.1 完成度指标
|
||||
|
||||
```
|
||||
DataModel CompletionData {
|
||||
──── 主线进程 ────────────────────
|
||||
mainQuestStage : Integer // 当前主线阶段
|
||||
endingUnlocked : Optional<EndingType>
|
||||
|
||||
──── 探索进度 ────────────────────
|
||||
roomsVisited : Set<ID> // 已访问房间
|
||||
mapRevealPercent: Number // 0.0~1.0
|
||||
|
||||
──── 收集进度 ────────────────────
|
||||
maxHPUpCount : Integer // 已拾取 HP 上限碎片数
|
||||
maxSoulUpCount : Integer // 已拾取灵力上限碎片数
|
||||
maxSpiritUpCount: Integer // 已拾取魄元上限碎片数
|
||||
lorePiecesFound : Set<ID>
|
||||
|
||||
──── 挑战进度 ────────────────────
|
||||
bossesDefeated : Set<ID>
|
||||
bossesParried : Set<ID> // 弹反过 Boss 至少一次
|
||||
secretsFound : Set<ID>
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 三结局条件
|
||||
|
||||
| 结局 | 触发条件 |
|
||||
|------|---------|
|
||||
| **结局 A**(普通结局)| 击败最终 Boss,未满足结局 B/C 条件 |
|
||||
| **结局 B**(完全结局)| 击败所有 Boss + 主线所有剧情节点 + 特定 NPC 任务完成 |
|
||||
| **结局 C**(隐藏结局)| 发现隐藏区域、触发特定世界标记序列 + 结局 B 条件 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 护符系统
|
||||
|
||||
### 6.1 护符数据模型
|
||||
|
||||
```
|
||||
DataModel CharmData {
|
||||
charmId : ID
|
||||
displayName : String
|
||||
description : String
|
||||
──────────────────────────────────
|
||||
notchCost : Integer // 装备槽位消耗
|
||||
──────────────────────────────────
|
||||
effects : List<CharmEffect>
|
||||
comboCharms : Optional<List<ID>> // 与哪些护符组合触发强化效果
|
||||
comboEffects : Optional<List<CharmEffect>>
|
||||
}
|
||||
|
||||
DataModel CharmEffect {
|
||||
effectType : CharmEffectType
|
||||
params : Map<String, Number>
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 护符槽位规则
|
||||
|
||||
| 规则项 | 说明 |
|
||||
|--------|------|
|
||||
| 初始槽位 | 3 个 Notch |
|
||||
| 扩展方式 | 特定 NPC(付 Geo)增加 Notch |
|
||||
| 最大 Notch | 11 个(初始 3 + 最多可购买 8)|
|
||||
| 过量装备 | 可强行装备超过槽位(超出则 HP 上限临时减半)|
|
||||
|
||||
### 6.3 护符效果类型
|
||||
|
||||
| 类型 | 说明 | 参数 |
|
||||
|------|------|------|
|
||||
| `StatModifier` | 修改某资源上限/恢复量 | `statType`, `delta` |
|
||||
| `DamageModifier` | 修改某类攻击的伤害倍率 | `attackType`, `multiplier` |
|
||||
| `WeaponOverride` | 覆盖某形态的武器 | `formId`, `weaponId` |
|
||||
| `SkillModifier` | 修改技能效果参数 | `skillId`, `paramKey`, `newValue` |
|
||||
| `AerialDashCount` | 增加空中冲刺充能次数 | `additionalCharges` |
|
||||
| `ParryWindowExpand` | 扩大弹反时间窗口 | `addedSeconds` |
|
||||
| `OnHitEffect` | 命中时附加效果 | `effectType`, `chance` |
|
||||
|
||||
---
|
||||
|
||||
## 7. 进程事件目录
|
||||
|
||||
| 事件 | 触发时机 | 载荷 |
|
||||
|------|---------|------|
|
||||
| `OnAbilityUnlocked` | 获得新能力 | `abilityId` |
|
||||
| `OnGateUnlocked` | 门控条件满足,门开启 | `gateId` |
|
||||
| `OnCharmEquipped` | 装备护符 | `charmId, slotIndex` |
|
||||
| `OnCharmUnequipped` | 卸下护符 | `charmId` |
|
||||
| `OnCharmComboActivated` | 护符组合效果触发 | `charmIds: List<ID>` |
|
||||
| `OnGeoShadeCreated` | 死亡创建遗骸 | `position, amount` |
|
||||
| `OnGeoShadeRecovered` | 拾取遗骸 | `amount` |
|
||||
| `OnGeoShadeLost` | 遗骸永久消失 | `amount` |
|
||||
| `OnEndingUnlocked` | 结局条件满足 | `endingType` |
|
||||
| `OnCompletionMilestone` | 完成度达到里程碑 | `milestoneId, percent` |
|
||||
168
Docs/DesignSpec/10_UISystem.md
Normal file
168
Docs/DesignSpec/10_UISystem.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# 10 · UI 系统规范
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:游戏 UI 分层架构、HUD 元素规范、菜单系统与 UI 事件契约。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [UI 设计原则](#1-ui-设计原则)
|
||||
2. [UI 分层架构](#2-ui-分层架构)
|
||||
3. [HUD 规范](#3-hud-规范)
|
||||
4. [菜单系统](#4-菜单系统)
|
||||
5. [UI 数据绑定契约](#5-ui-数据绑定契约)
|
||||
6. [UI 事件目录](#6-ui-事件目录)
|
||||
|
||||
---
|
||||
|
||||
## 1. UI 设计原则
|
||||
|
||||
| 原则 | 说明 |
|
||||
|------|------|
|
||||
| **非侵入** | HUD 元素尽量小,不遮挡游戏视野 |
|
||||
| **信息即时** | 关键状态变化立即反映(HP减少不延迟)|
|
||||
| **纯响应式** | UI 不主动查询游戏状态,只响应事件 |
|
||||
| **逻辑无关** | UI 不包含任何游戏逻辑,仅负责显示与交互 |
|
||||
|
||||
---
|
||||
|
||||
## 2. UI 分层架构
|
||||
|
||||
从最低层到最高层:
|
||||
|
||||
| 层级 | 名称 | 内容 | 说明 |
|
||||
|------|------|------|------|
|
||||
| Layer 0 | Game World | 游戏本体 | 非 UI |
|
||||
| Layer 1 | World UI | 对话气泡、头顶血条 | 跟随世界坐标 |
|
||||
| Layer 2 | HUD | 血量/资源/护符 | 全程显示 |
|
||||
| Layer 3 | Notification | 弹出提示、成就 | 临时覆盖 |
|
||||
| Layer 4 | Overlay Menu | 暂停、设置 | 半透明遮罩 |
|
||||
| Layer 5 | Full-screen | 存档读取、过场动画 | 完全遮盖 |
|
||||
| Layer 6 | Transition | 场景转场动画 | 最高优先级 |
|
||||
|
||||
---
|
||||
|
||||
## 3. HUD 规范
|
||||
|
||||
### 3.1 HUD 元素列表
|
||||
|
||||
| 元素 | 位置 | 显示内容 |
|
||||
|------|------|---------|
|
||||
| HP 条 | 左上角 | 当前 HP / 最大 HP,格子式显示 |
|
||||
| 灵泉指示 | HP 条下方 | 灵泉数量(图标×N)|
|
||||
| 灵力条 | 左下角 | 当前灵力(填充环形或条形)|
|
||||
| 魄元条 | 灵力条旁 | 当前魄元 |
|
||||
| 形态指示 | 右下角 | 当前形态图标 + 三形态小图标 |
|
||||
| 技能槽 | 形态指示旁 | 当前形态的魂技能/魄技能图标 + 冷却遮罩 |
|
||||
| Geo 计数 | 右上角(可选)| 当前 Geo 数量 |
|
||||
| Boss 血条 | 屏幕下方居中 | 仅 Boss 战显示,含阶段分段标记 |
|
||||
|
||||
### 3.2 HP 显示规范
|
||||
|
||||
- 每格 = 固定 HP 量(如每格 = 50 HP)
|
||||
- 满格:实心图标
|
||||
- 半格(受伤未满格):半空状态
|
||||
- 空格:空心图标
|
||||
- 当前 HP < 20%:格子闪烁警告
|
||||
- HP 变化时:格子动画(减少时格子渐消,恢复时渐现)
|
||||
|
||||
### 3.3 形态指示规范
|
||||
|
||||
- 当前激活形态:大图标高亮
|
||||
- 其他两形态:小图标、低亮度
|
||||
- 切换时:当前形态图标播放切换动画,新形态高亮
|
||||
|
||||
---
|
||||
|
||||
## 4. 菜单系统
|
||||
|
||||
### 4.1 菜单层级
|
||||
|
||||
```
|
||||
主菜单
|
||||
├── 继续游戏
|
||||
├── 新游戏
|
||||
├── 存档选择
|
||||
└── 设置
|
||||
├── 图像设置
|
||||
├── 音频设置
|
||||
├── 操控设置
|
||||
└── 辅助设置
|
||||
|
||||
暂停菜单(游戏中)
|
||||
├── 继续
|
||||
├── 地图
|
||||
├── 护符装备
|
||||
├── 道具/图鉴
|
||||
├── 设置
|
||||
└── 返回主菜单(确认弹窗)
|
||||
```
|
||||
|
||||
### 4.2 菜单状态管理
|
||||
|
||||
```
|
||||
菜单系统维护一个菜单栈(Stack):
|
||||
|
||||
打开菜单:
|
||||
→ 新菜单 push 到栈顶
|
||||
→ 暂停游戏时间(若为暂停菜单)
|
||||
→ 新菜单获得输入焦点
|
||||
|
||||
关闭/返回:
|
||||
→ 当前菜单 pop
|
||||
→ 若栈空 → 游戏恢复运行
|
||||
|
||||
关闭所有菜单:
|
||||
→ 清空栈
|
||||
→ 游戏立即恢复
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. UI 数据绑定契约
|
||||
|
||||
UI 不直接访问游戏数据,通过以下接口获取信息:
|
||||
|
||||
```
|
||||
Interface IHUDDataProvider {
|
||||
getPlayerHP() → {current: Integer, max: Integer}
|
||||
getPlayerSoul() → {current: Integer, max: Integer}
|
||||
getPlayerSpirit() → {current: Integer, max: Integer}
|
||||
getSpringCount() → Integer
|
||||
getCurrentForm() → FormData
|
||||
getActiveCharms() → List<CharmData>
|
||||
getGeoAmount() → Integer
|
||||
}
|
||||
|
||||
Interface IBossHUDProvider {
|
||||
getBossHP() → {current: Integer, max: Integer}
|
||||
getBossPhaseCount() → Integer
|
||||
getBossPhaseThresholds() → List<Number> // 各阶段 HP 百分比
|
||||
getBossName() → String
|
||||
}
|
||||
```
|
||||
|
||||
UI 监听事件更新显示,不轮询接口(接口仅供初始化或主动请求使用)。
|
||||
|
||||
---
|
||||
|
||||
## 6. UI 事件目录
|
||||
|
||||
| 事件 | 触发者 | UI 响应 |
|
||||
|------|--------|---------|
|
||||
| `OnPlayerHPChanged` | 玩家系统 | 刷新 HP 格子 |
|
||||
| `OnPlayerSoulChanged` | 玩家系统 | 刷新灵力条 |
|
||||
| `OnPlayerSpiritChanged` | 玩家系统 | 刷新魄元条 |
|
||||
| `OnSpringCountChanged` | 玩家系统 | 刷新灵泉图标 |
|
||||
| `OnFormChanged` | 形态系统 | 刷新形态指示 |
|
||||
| `OnBossEncounterBegin` | 世界系统 | 显示 Boss 血条 |
|
||||
| `OnBossHPChanged` | Boss | 刷新 Boss 血条 |
|
||||
| `OnBossPhaseChanged` | Boss | Boss 血条阶段标记动画 |
|
||||
| `OnBossDefeated` | Boss | 隐藏 Boss 血条(动画)|
|
||||
| `OnSkillCooldownUpdated` | 技能系统 | 刷新技能冷却遮罩 |
|
||||
| `OnCharmEquipped` | 进程系统 | 刷新护符栏 |
|
||||
| `OnNotification` | 任意系统 | 显示弹出通知 |
|
||||
| `OnMenuOpen` | 输入系统 | 打开暂停菜单 |
|
||||
| `OnDialogueStarted` | 叙事系统 | 显示对话框 |
|
||||
| `OnDialogueEnded` | 叙事系统 | 隐藏对话框 |
|
||||
182
Docs/DesignSpec/11_AudioSystem.md
Normal file
182
Docs/DesignSpec/11_AudioSystem.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# 11 · 音频系统规范
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:音频分层架构、自适应音乐系统、音效触发契约与音量管理。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [音频设计原则](#1-音频设计原则)
|
||||
2. [音频分层架构](#2-音频分层架构)
|
||||
3. [自适应音乐系统](#3-自适应音乐系统)
|
||||
4. [音效(SFX)规范](#4-音效sfx规范)
|
||||
5. [音频总线与混音](#5-音频总线与混音)
|
||||
6. [音频事件目录](#6-音频事件目录)
|
||||
|
||||
---
|
||||
|
||||
## 1. 音频设计原则
|
||||
|
||||
| 原则 | 说明 |
|
||||
|------|------|
|
||||
| **情境响应** | 音乐随战斗/探索状态自动切换层级 |
|
||||
| **游戏反馈优先** | 每个玩家动作都有清晰音效反馈(攻击/受伤/弹反)|
|
||||
| **非侵入性** | 非战斗状态音乐保持安静,不与游戏音效竞争 |
|
||||
| **数据驱动** | 音频配置和触发条件通过数据定义,不硬编码 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 音频分层架构
|
||||
|
||||
```
|
||||
AudioSystem(协调器)
|
||||
├── MusicPlayer ← 背景音乐、自适应分层
|
||||
├── AmbiencePlayer ← 环境音效(风声、水声等)
|
||||
├── SFXPool ← 音效池,管理 SFX 实例
|
||||
└── VoicePlayer ← 对话/语音(若有)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 自适应音乐系统
|
||||
|
||||
### 3.1 音乐状态机
|
||||
|
||||
```
|
||||
[Silence] ──加载区域──► [Exploration]
|
||||
[Exploration] ──感知敌人──► [CombatIntro]
|
||||
[CombatIntro] ──0.5s──► [Combat]
|
||||
[Combat] ──清场/脱战─────► [CombatOutro]
|
||||
[CombatOutro] ──1.0s────► [Exploration]
|
||||
[Exploration] ──进入Boss房间──► [BossIntro]
|
||||
[BossIntro] ──播放完毕──► [BossPhase1]
|
||||
[BossPhase1] ──阶段转换──► [BossPhase2]
|
||||
[BossPhase2] ──Boss死亡──► [BossVictory]
|
||||
[BossVictory] ──播放完毕──► [Exploration]
|
||||
```
|
||||
|
||||
### 3.2 音乐分层(Layer)
|
||||
|
||||
每首区域音乐由多个同步的音频层叠加:
|
||||
|
||||
| 层 | 说明 | 探索 | 战斗 |
|
||||
|----|------|:----:|:----:|
|
||||
| Base | 旋律主干 | ✓ | ✓ |
|
||||
| Percussion | 打击乐 | 弱 | ✓ |
|
||||
| Tension | 紧张弦乐 | ✗ | ✓ |
|
||||
| Ambient | 环境填充 | ✓ | ✗ |
|
||||
| BossLayer | Boss 专属 | ✗ | Boss战 |
|
||||
|
||||
层级混合通过音量淡入淡出(crossfade)实现,切换时间可配置。
|
||||
|
||||
### 3.3 音乐数据模型
|
||||
|
||||
```
|
||||
DataModel MusicData {
|
||||
musicId : ID
|
||||
regionId : ID // 归属区域
|
||||
──────────────────────────────────
|
||||
layers : Map<MusicLayer, AudioID> // 各层音频资源
|
||||
bpm : Integer // 用于节拍同步切换
|
||||
loopStart : Duration
|
||||
loopEnd : Duration
|
||||
──────────────────────────────────
|
||||
transitionMode : TransitionMode // 即时/等待小节/淡入淡出
|
||||
crossfadeDuration: Duration
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 音效(SFX)规范
|
||||
|
||||
### 4.1 音效触发契约
|
||||
|
||||
```
|
||||
Interface IAudioTrigger {
|
||||
playOneShot(audioId: AudioID, position: Optional<Vector2>) → Void
|
||||
playLooping(audioId: AudioID, handle: out AudioHandle) → Void
|
||||
stopLooping(handle: AudioHandle) → Void
|
||||
playWithVariation(audioId: AudioID, pitchRange: {min,max}) → Void
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 玩家动作音效列表
|
||||
|
||||
| 动作 | 音效 | 变调范围 |
|
||||
|------|------|---------|
|
||||
| 普通攻击 1/2/3 | `sfx_attack_1/2/3` | ±0.05 |
|
||||
| 受伤 | `sfx_hurt` | ±0.1 |
|
||||
| 死亡 | `sfx_death` | — |
|
||||
| 弹反成功 | `sfx_parry_success` | — |
|
||||
| 弹反失败(时机错误)| `sfx_parry_fail` | — |
|
||||
| 跳跃 | `sfx_jump` | ±0.08 |
|
||||
| 双跳 | `sfx_double_jump` | ±0.05 |
|
||||
| 冲刺 | `sfx_dash` | — |
|
||||
| 空中冲刺 | `sfx_aerial_dash` | — |
|
||||
| 下冲落地 | `sfx_plunge_land` | — |
|
||||
| 墙跳 | `sfx_wall_jump` | ±0.05 |
|
||||
| 形态切换 | `sfx_form_switch_{formId}` | — |
|
||||
| 技能施放 | `sfx_skill_{skillId}` | — |
|
||||
| 灵泉使用 | `sfx_spring_use` | — |
|
||||
| 拾取 Geo | `sfx_geo_collect` | ±0.1 |
|
||||
|
||||
### 4.3 音效变调规则
|
||||
|
||||
- **随机变调**(pitchVariation):相同音效连续触发时,随机微调音调,避免"机器声"感
|
||||
- **连击变调**:攻击 1→2→3 音效各自递进(音调略微提升,体现连击感)
|
||||
|
||||
---
|
||||
|
||||
## 5. 音频总线与混音
|
||||
|
||||
### 5.1 音频总线层级
|
||||
|
||||
```
|
||||
Master Bus
|
||||
├── Music Bus
|
||||
│ ├── Exploration Layer
|
||||
│ ├── Combat Layer
|
||||
│ └── Boss Layer
|
||||
├── SFX Bus
|
||||
│ ├── Player SFX
|
||||
│ ├── Enemy SFX
|
||||
│ └── World SFX
|
||||
└── UI Bus
|
||||
├── Menu SFX
|
||||
└── Notification SFX
|
||||
```
|
||||
|
||||
### 5.2 音量控制规范
|
||||
|
||||
| 总线 | 用户可调 | 默认值 |
|
||||
|------|---------|--------|
|
||||
| Master Bus | ✓ | 100% |
|
||||
| Music Bus | ✓ | 80% |
|
||||
| SFX Bus | ✓ | 100% |
|
||||
| UI Bus | ✓ | 90% |
|
||||
|
||||
> 所有用户音量设置持久化到 UserSettings(独立于 SaveData)
|
||||
|
||||
---
|
||||
|
||||
## 6. 音频事件目录
|
||||
|
||||
音频系统监听以下事件执行音频响应:
|
||||
|
||||
| 监听事件 | 音频响应 |
|
||||
|---------|---------|
|
||||
| `OnPlayerAttack` | 播放攻击音效 |
|
||||
| `OnPlayerHurt` | 播放受伤音效 |
|
||||
| `OnPlayerDied` | 播放死亡音效,切换到 Silence |
|
||||
| `OnParrySuccess` | 播放弹反成功音效 + 子弹时间音效处理 |
|
||||
| `OnFormChanged` | 播放形态切换音效 |
|
||||
| `OnBonfireRested` | 播放存档音效 |
|
||||
| `OnBossEncounterBegin` | 切换到 BossIntro 音乐 |
|
||||
| `OnBossPhaseChanged` | 切换音乐层/音乐轨道 |
|
||||
| `OnBossDefeated` | 播放 BossVictory 音乐 |
|
||||
| `OnRoomTransitionBegin` | 淡出当前音乐 |
|
||||
| `OnRoomTransitionComplete` | 根据新房间/区域加载新音乐 |
|
||||
| `OnCollectiblePickedUp` | 播放拾取音效(按类型)|
|
||||
| `OnEnemyDied` | 播放敌人死亡音效 |
|
||||
165
Docs/DesignSpec/12_EconomySystem.md
Normal file
165
Docs/DesignSpec/12_EconomySystem.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# 12 · 经济系统规范
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:Geo 货币体系、商店系统、掉落经济平衡与消费循环设计。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [经济设计原则](#1-经济设计原则)
|
||||
2. [Geo 货币体系](#2-geo-货币体系)
|
||||
3. [商店系统](#3-商店系统)
|
||||
4. [物品数据模型](#4-物品数据模型)
|
||||
5. [经济平衡参数](#5-经济平衡参数)
|
||||
6. [经济事件目录](#6-经济事件目录)
|
||||
|
||||
---
|
||||
|
||||
## 1. 经济设计原则
|
||||
|
||||
| 原则 | 说明 |
|
||||
|------|------|
|
||||
| **单一货币** | 只有 Geo,避免多货币系统带来的混乱 |
|
||||
| **死亡有意义** | 遗骸机制使 Geo 有风险感,强化决策权重 |
|
||||
| **非强制消费** | 所有商店物品为锦上添花,不买也能通关 |
|
||||
| **价格成长** | 后期物品价格随区域进程递增 |
|
||||
|
||||
---
|
||||
|
||||
## 2. Geo 货币体系
|
||||
|
||||
### 2.1 Geo 获取来源
|
||||
|
||||
| 来源 | 数量范围 | 说明 |
|
||||
|------|---------|------|
|
||||
| 击杀普通敌人 | 1-15 | 随敌人等级变化 |
|
||||
| 击杀精英怪 | 20-60 | |
|
||||
| 击杀 Boss | 100-500 | |
|
||||
| 拾取 GeoCache 收集品 | 固定值 | 地图中隐藏的 Geo 堆 |
|
||||
| 出售物品 | 物品定价 50% | 部分物品可出售 |
|
||||
| 完成 NPC 任务 | 任务奖励 | |
|
||||
|
||||
### 2.2 Geo 消耗途径
|
||||
|
||||
| 途径 | 数量范围 | 说明 |
|
||||
|------|---------|------|
|
||||
| 商店购买护符 | 100-1200 | 主要消耗 |
|
||||
| 商店购买消耗品 | 20-200 | |
|
||||
| Notch 扩展 | 递增(150/300/500...)| 扩展护符槽位 |
|
||||
| 门控通行费 | 固定值 | 某些区域收费通道 |
|
||||
| NPC 服务 | 固定值 | 特殊 NPC 的服务费 |
|
||||
|
||||
### 2.3 Geo 上限
|
||||
|
||||
| 规则 | 说明 |
|
||||
|------|------|
|
||||
| 携带上限 | 无上限(设计上不设置)|
|
||||
| 遗骸上限 | 携带量全部转为遗骸 |
|
||||
| 显示格式 | 整数,无小数点 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 商店系统
|
||||
|
||||
### 3.1 商店数据模型
|
||||
|
||||
```
|
||||
DataModel ShopData {
|
||||
shopId : ID
|
||||
shopkeeperNpcId : ID // 关联 NPC
|
||||
──────────────────────────────────
|
||||
inventory : List<ShopItemEntry>
|
||||
refreshCondition: Optional<RefreshCondition> // 何时刷新库存
|
||||
welcomeText : String
|
||||
}
|
||||
|
||||
DataModel ShopItemEntry {
|
||||
itemId : Ref<ItemData>
|
||||
basePrice : Integer
|
||||
stock : Optional<Integer> // null = 无限库存
|
||||
availableCondition: Optional<GateCondition> // 解锁条件(null=始终可购)
|
||||
discountFlags : Optional<Flags<DiscountSource>> // 折扣来源
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 购买流程
|
||||
|
||||
```
|
||||
玩家在商店 UI 选择物品并确认购买:
|
||||
→ 检查玩家 Geo >= itemPrice
|
||||
├─ 不足 → 显示"Geo 不足"提示,取消
|
||||
└─ 足够 →
|
||||
→ 扣除 playerGeo -= itemPrice
|
||||
→ 将物品加入玩家库存(或直接应用效果)
|
||||
→ 若有 stock,stock -= 1
|
||||
→ stock == 0 时,从列表中移除该项
|
||||
→ 发出 OnShopPurchase 事件
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 物品数据模型
|
||||
|
||||
```
|
||||
DataModel ItemData {
|
||||
itemId : ID
|
||||
displayName : String
|
||||
description : String
|
||||
──────────────────────────────────
|
||||
itemType : ItemType // 护符/消耗品/关键道具/图鉴
|
||||
stackable : Boolean
|
||||
maxStack : Optional<Integer> // null = 无限叠加
|
||||
──────────────────────────────────
|
||||
useEffect : Optional<Ref<UseEffectData>> // 使用效果(消耗品)
|
||||
sellValue : Optional<Integer> // null = 不可出售
|
||||
}
|
||||
```
|
||||
|
||||
### 4.1 物品类型
|
||||
|
||||
| 类型 | 说明 | 叠加 |
|
||||
|------|------|------|
|
||||
| `Charm` | 护符,装备型 | 不叠加(每种只有 1 个)|
|
||||
| `Consumable` | 消耗品,使用即激活效果 | 叠加,最多 9 个/槽 |
|
||||
| `KeyItem` | 关键道具,推进剧情/开门 | 不叠加 |
|
||||
| `LoreItem` | 世界观物品,加入图鉴 | 不叠加 |
|
||||
| `Map` | 区域地图碎片 | 不叠加 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 经济平衡参数
|
||||
|
||||
### 5.1 区域 Geo 密度(参考)
|
||||
|
||||
| 游戏阶段 | 单次刷怪平均 Geo | 护符平均价格 |
|
||||
|---------|---------------|------------|
|
||||
| 早期区域(1-2 区)| 5-20 | 100-300 |
|
||||
| 中期区域(3-4 区)| 15-50 | 400-700 |
|
||||
| 后期区域(5+ 区)| 40-120 | 800-1200 |
|
||||
|
||||
> **平衡原则**:购买一件中期护符约需清扫 2-3 个房间的敌人,不应过长也不应过短。
|
||||
|
||||
### 5.2 Notch 扩展价格表
|
||||
|
||||
| 第 N 次扩展 | 价格(Geo)|
|
||||
|-----------|-----------|
|
||||
| 1 | 150 |
|
||||
| 2 | 300 |
|
||||
| 3 | 500 |
|
||||
| 4 | 800 |
|
||||
| 5 | 1200 |
|
||||
| 6+ | 递增 500/次 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 经济事件目录
|
||||
|
||||
| 事件 | 触发时机 | 载荷 |
|
||||
|------|---------|------|
|
||||
| `OnGeoChanged` | Geo 数量变化 | `delta: Integer, newTotal: Integer` |
|
||||
| `OnShopOpened` | 打开商店 | `shopId` |
|
||||
| `OnShopPurchase` | 完成购买 | `shopId, itemId, price` |
|
||||
| `OnItemAcquired` | 获得任何物品 | `itemId, source` |
|
||||
| `OnItemUsed` | 使用消耗品 | `itemId` |
|
||||
| `OnNotchExpanded` | 扩展护符槽 | `newNotchCount, geoCost` |
|
||||
216
Docs/DesignSpec/13_SaveSystem.md
Normal file
216
Docs/DesignSpec/13_SaveSystem.md
Normal file
@@ -0,0 +1,216 @@
|
||||
# 13 · 存档系统规范
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:存档数据结构(Schema)、读写契约、版本迁移与存档槽管理。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [存档设计原则](#1-存档设计原则)
|
||||
2. [存档数据 Schema](#2-存档数据-schema)
|
||||
3. [存档读写契约](#3-存档读写契约)
|
||||
4. [存档触发时机](#4-存档触发时机)
|
||||
5. [版本迁移规范](#5-版本迁移规范)
|
||||
6. [存档槽管理](#6-存档槽管理)
|
||||
|
||||
---
|
||||
|
||||
## 1. 存档设计原则
|
||||
|
||||
| 原则 | 说明 |
|
||||
|------|------|
|
||||
| **单一来源** | 存档数据是游戏状态的唯一持久化来源 |
|
||||
| **原子性** | 存档要么完整写入,要么不写(不产生损坏的存档)|
|
||||
| **版本兼容** | 旧版存档可被新版游戏读取(向前兼容)|
|
||||
| **与引擎无关** | 存档格式为纯数据(JSON / 结构化二进制),不依赖引擎序列化 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 存档数据 Schema
|
||||
|
||||
### 2.1 顶层结构
|
||||
|
||||
```
|
||||
DataModel SaveData {
|
||||
──── 元信息 ────────────────────────
|
||||
schemaVersion : Integer // 用于版本迁移
|
||||
saveSlot : Integer // 存档槽编号(1-3)
|
||||
lastSaveTime : String // ISO 8601 时间戳
|
||||
playTimeSecs : Integer // 游戏内游玩时长(秒)
|
||||
|
||||
──── 玩家状态 ──────────────────────
|
||||
player : PlayerSaveData
|
||||
|
||||
──── 世界状态 ──────────────────────
|
||||
world : WorldSaveData
|
||||
|
||||
──── 进程 ──────────────────────────
|
||||
progression : ProgressionSaveData
|
||||
|
||||
──── 经济 ──────────────────────────
|
||||
economy : EconomySaveData
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 玩家存档数据
|
||||
|
||||
```
|
||||
DataModel PlayerSaveData {
|
||||
currentHP : Integer
|
||||
maxHP : Integer
|
||||
maxSoulPower : Integer
|
||||
maxSpiritPower : Integer
|
||||
springCount : Integer
|
||||
geoAmount : Integer
|
||||
|
||||
currentFormId : ID
|
||||
unlockedFormIds : List<ID>
|
||||
|
||||
equippedCharmIds: List<ID> // 当前装备的护符
|
||||
inventoryItems : List<{itemId: ID, count: Integer}>
|
||||
|
||||
lastBonfireId : ID // 死亡后重生位置
|
||||
lastRoomId : ID // 关闭游戏前所在房间
|
||||
lastPosition : Vector2 // 关闭游戏前的精确位置
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 世界存档数据
|
||||
|
||||
```
|
||||
DataModel WorldSaveData {
|
||||
visitedRoomIds : List<ID>
|
||||
activatedBonfireIds: List<ID>
|
||||
|
||||
defeatedBossIds : List<ID>
|
||||
permanentlyDeadEnemyIds: List<ID> // 不刷新的特殊敌人
|
||||
|
||||
openedGateIds : List<ID>
|
||||
activatedSwitchIds: List<ID>
|
||||
|
||||
collectedCollectibleIds: List<ID>
|
||||
|
||||
geoShade : Optional<GeoShadeState> // 见 09_ProgressionSystem
|
||||
}
|
||||
```
|
||||
|
||||
### 2.4 进程存档数据
|
||||
|
||||
```
|
||||
DataModel ProgressionSaveData {
|
||||
unlockedAbilityIds: List<ID>
|
||||
|
||||
mainQuestStage : Integer
|
||||
completedQuestIds: List<ID>
|
||||
worldFlags : Map<String, Boolean> // 任意世界状态标记
|
||||
|
||||
notchCount : Integer
|
||||
purchasedNotchCount: Integer
|
||||
|
||||
loreFoundIds : List<ID>
|
||||
secretsFoundIds : List<ID>
|
||||
|
||||
lootPityCounters: Map<ID, Integer> // 保底计数(itemId → 未掉落次数)
|
||||
}
|
||||
```
|
||||
|
||||
### 2.5 经济存档数据
|
||||
|
||||
```
|
||||
DataModel EconomySaveData {
|
||||
ownedCharmIds : List<ID> // 已获得(非已装备)的护符
|
||||
shopPurchaseHistory: Map<ID, List<ID>> // shopId → 已购买 itemId 列表
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 存档读写契约
|
||||
|
||||
```
|
||||
Interface ISaveSystem {
|
||||
// 写入
|
||||
save(data: SaveData, slot: Integer) → SaveResult
|
||||
|
||||
// 读取
|
||||
load(slot: Integer) → Optional<SaveData>
|
||||
|
||||
// 检查
|
||||
slotExists(slot: Integer) → Boolean
|
||||
getSlotMetadata(slot: Integer) → Optional<SaveSlotMeta>
|
||||
|
||||
// 删除(需二次确认)
|
||||
deleteSlot(slot: Integer) → Void
|
||||
}
|
||||
|
||||
DataModel SaveSlotMeta {
|
||||
slot : Integer
|
||||
lastSaveTime : String
|
||||
playTimeSecs : Integer
|
||||
lastRoomName : String
|
||||
playerHP : Integer
|
||||
maxHP : Integer
|
||||
}
|
||||
|
||||
DataModel SaveResult {
|
||||
success : Boolean
|
||||
error : Optional<String>
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 存档触发时机
|
||||
|
||||
| 触发事件 | 存档类型 | 说明 |
|
||||
|---------|---------|------|
|
||||
| `OnBonfireRested` | 完整存档 | 最主要的存档时机 |
|
||||
| `OnCollectiblePickedUp`(关键道具)| 完整存档 | 防止关键进程丢失 |
|
||||
| `OnBossDefeated` | 完整存档 | Boss 死亡立即存档 |
|
||||
| `OnAbilityUnlocked` | 完整存档 | 防止能力解锁丢失 |
|
||||
| 游戏退出(发出退出信号)| 位置快照 | 保存位置,不算正式存档进度 |
|
||||
|
||||
> **设计决策**:不提供手动存档按钮
|
||||
> **原因**:存档点机制是游戏节奏设计的一部分,强制存档会破坏张力
|
||||
|
||||
---
|
||||
|
||||
## 5. 版本迁移规范
|
||||
|
||||
### 5.1 版本号规则
|
||||
|
||||
- `schemaVersion` 每次修改 SaveData 结构时递增
|
||||
- 不向后兼容(新版存档无法在旧版游戏中读取)
|
||||
- 向前兼容(旧版存档可被新版游戏迁移后读取)
|
||||
|
||||
### 5.2 迁移契约
|
||||
|
||||
```
|
||||
Interface ISaveMigrator {
|
||||
canMigrate(fromVersion: Integer, toVersion: Integer) → Boolean
|
||||
migrate(data: RawSaveData, fromVersion: Integer) → SaveData
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 迁移策略
|
||||
|
||||
| 变更类型 | 处理方式 |
|
||||
|---------|---------|
|
||||
| 新增字段 | 旧存档中该字段赋默认值 |
|
||||
| 删除字段 | 读取时忽略多余字段 |
|
||||
| 字段重命名 | 迁移器执行映射 |
|
||||
| 字段类型变更 | 迁移器执行转换逻辑 |
|
||||
| 无法迁移 | 提示玩家,提供新开局选项(不自动删除)|
|
||||
|
||||
---
|
||||
|
||||
## 6. 存档槽管理
|
||||
|
||||
| 规格项 | 值 |
|
||||
|--------|-----|
|
||||
| 存档槽数量 | 3 个 |
|
||||
| 每槽独立 | 完全独立,互不影响 |
|
||||
| 新游戏 | 选择存档槽 → 若已有存档显示警告 → 确认后覆盖 |
|
||||
| 存档文件位置 | 用户数据目录(不与游戏安装目录混存)|
|
||||
| 备份 | 写入前备份旧文件为 `.bak`,写入成功后删除备份 |
|
||||
248
Docs/DesignSpec/14_NarrativeSystem.md
Normal file
248
Docs/DesignSpec/14_NarrativeSystem.md
Normal file
@@ -0,0 +1,248 @@
|
||||
# 14 · 叙事系统规范
|
||||
|
||||
> **所属文档集** [← 返回索引](./README.md)
|
||||
> **摘要**:对话系统、世界标记、NPC 状态管理与三结局触发逻辑。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
1. [叙事设计原则](#1-叙事设计原则)
|
||||
2. [对话系统](#2-对话系统)
|
||||
3. [世界标记系统](#3-世界标记系统)
|
||||
4. [NPC 状态管理](#4-npc-状态管理)
|
||||
5. [任务系统](#5-任务系统)
|
||||
6. [结局触发系统](#6-结局触发系统)
|
||||
7. [叙事事件目录](#7-叙事事件目录)
|
||||
|
||||
---
|
||||
|
||||
## 1. 叙事设计原则
|
||||
|
||||
| 原则 | 说明 |
|
||||
|------|------|
|
||||
| **环境叙事优先** | 通过场景、图鉴和道具描述讲述故事,减少强制对话 |
|
||||
| **非线性探索** | 玩家可按任意顺序解锁叙事内容 |
|
||||
| **状态感知** | NPC 的对话随玩家进程改变(不重复同一句话)|
|
||||
| **数据驱动** | 所有对话树、条件和触发均为数据,不硬编码 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 对话系统
|
||||
|
||||
### 2.1 对话数据模型
|
||||
|
||||
```
|
||||
DataModel DialogueData {
|
||||
dialogueId : ID
|
||||
speakerId : ID // NPC ID 或 "player"
|
||||
──────────────────────────────────
|
||||
nodes : List<DialogueNode>
|
||||
entryNodeId : ID // 起始节点
|
||||
}
|
||||
|
||||
DataModel DialogueNode {
|
||||
nodeId : ID
|
||||
type : DialogueNodeType // Text / Choice / Condition / Action
|
||||
──────────────────────────────────
|
||||
// type = Text:
|
||||
text : Optional<String> // 支持本地化 Key
|
||||
portrait : Optional<PortraitID>
|
||||
nextNodeId : Optional<ID> // null = 对话结束
|
||||
|
||||
// type = Choice:
|
||||
choices : Optional<List<DialogueChoice>>
|
||||
|
||||
// type = Condition:
|
||||
condition : Optional<DialogueCondition>
|
||||
trueNodeId : Optional<ID>
|
||||
falseNodeId : Optional<ID>
|
||||
|
||||
// type = Action:
|
||||
action : Optional<DialogueAction>
|
||||
nextNodeId : Optional<ID>
|
||||
}
|
||||
|
||||
DataModel DialogueChoice {
|
||||
choiceText : String
|
||||
nextNodeId : ID
|
||||
availableCondition: Optional<DialogueCondition> // null=始终显示
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 对话条件类型
|
||||
|
||||
```
|
||||
DataModel DialogueCondition {
|
||||
conditionType : DialogueConditionType
|
||||
targetId : Optional<ID>
|
||||
value : Optional<Number>
|
||||
}
|
||||
```
|
||||
|
||||
| 条件类型 | 说明 |
|
||||
|---------|------|
|
||||
| `HasAbility` | 玩家已解锁某能力 |
|
||||
| `HasItem` | 玩家持有某物品 |
|
||||
| `WorldFlagTrue` | 某世界标记为 true |
|
||||
| `QuestStageIs` | 某任务处于指定阶段 |
|
||||
| `BossDefeated` | 某 Boss 已被击败 |
|
||||
| `FirstVisit` | 玩家第一次和此 NPC 对话 |
|
||||
|
||||
### 2.3 对话动作类型
|
||||
|
||||
| 动作类型 | 说明 |
|
||||
|---------|------|
|
||||
| `SetWorldFlag` | 设置世界标记 |
|
||||
| `GiveItem` | 给予物品 |
|
||||
| `GiveGeo` | 给予 Geo |
|
||||
| `UnlockAbility` | 解锁能力 |
|
||||
| `AdvanceQuest` | 推进任务阶段 |
|
||||
| `PlayCutscene` | 播放过场动画 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 世界标记系统
|
||||
|
||||
### 3.1 世界标记规范
|
||||
|
||||
```
|
||||
WorldFlags: Map<String, Boolean>
|
||||
```
|
||||
|
||||
- 存储于 `ProgressionSaveData.worldFlags`
|
||||
- Key 为字符串,建议命名格式:`区域_事件_描述`(如 `region1_boss_firstEncounter`)
|
||||
- 标记只能设为 true,不支持撤销(设计保证单向性)
|
||||
- 叙事系统、门控系统、AI 系统均可读取世界标记
|
||||
|
||||
### 3.2 设置世界标记的来源
|
||||
|
||||
| 来源 | 说明 |
|
||||
|------|------|
|
||||
| 对话动作 `SetWorldFlag` | 对话选择/到达某节点时触发 |
|
||||
| 门控开启 | 某些门控开启时自动设置 |
|
||||
| Boss 死亡 | OnBossDefeated 事件触发时自动设置 |
|
||||
| 收集品拾取 | 特定关键收集品触发 |
|
||||
| 手动触发器 | 场景中的触发区域触碰时 |
|
||||
|
||||
---
|
||||
|
||||
## 4. NPC 状态管理
|
||||
|
||||
### 4.1 NPC 数据模型
|
||||
|
||||
```
|
||||
DataModel NPCData {
|
||||
npcId : ID
|
||||
displayName : String
|
||||
──────────────────────────────────
|
||||
locations : List<NPCLocationEntry> // NPC 在不同阶段的位置
|
||||
dialogueVersions: List<NPCDialogueVersion> // 不同进程阶段的对话
|
||||
}
|
||||
|
||||
DataModel NPCLocationEntry {
|
||||
condition : Optional<DialogueCondition> // 满足时位于此处(null=默认)
|
||||
roomId : ID
|
||||
position : Vector2
|
||||
}
|
||||
|
||||
DataModel NPCDialogueVersion {
|
||||
condition : Optional<DialogueCondition> // 满足时使用此对话(null=默认)
|
||||
dialogueId : ID
|
||||
priority : Integer // 多个条件同时满足时取最高优先级
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 对话版本选取规则
|
||||
|
||||
```
|
||||
玩家与 NPC 交互时:
|
||||
|
||||
枚举 NPCData.dialogueVersions(按 priority 降序)
|
||||
→ 找第一个 condition 满足(或 condition 为 null)的版本
|
||||
→ 使用该版本的 dialogueId 开始对话
|
||||
|
||||
若无任何版本满足 → 使用默认兜底对话("......")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 任务系统
|
||||
|
||||
### 5.1 任务数据模型
|
||||
|
||||
```
|
||||
DataModel QuestData {
|
||||
questId : ID
|
||||
displayName : String
|
||||
description : String
|
||||
──────────────────────────────────
|
||||
stages : List<QuestStageData>
|
||||
rewardOnComplete: Optional<QuestReward>
|
||||
}
|
||||
|
||||
DataModel QuestStageData {
|
||||
stageIndex : Integer
|
||||
description : String
|
||||
completionCondition: DialogueCondition // 推进到下一阶段的条件
|
||||
}
|
||||
|
||||
DataModel QuestReward {
|
||||
geoAmount : Optional<Integer>
|
||||
itemIds : List<ID>
|
||||
abilityId : Optional<ID>
|
||||
worldFlagsToSet : List<String>
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 结局触发系统
|
||||
|
||||
### 6.1 结局条件回顾
|
||||
|
||||
(详细条件见 [09_ProgressionSystem.md](09_ProgressionSystem.md) 第 5 节)
|
||||
|
||||
| 结局 | 类型 | 核心条件 |
|
||||
|------|------|---------|
|
||||
| 结局 A | 普通 | 击败最终 Boss |
|
||||
| 结局 B | 完全 | Boss 全清 + 主线剧情完整 + 关键 NPC 任务 |
|
||||
| 结局 C | 隐藏 | 结局 B + 隐藏世界标记序列激活 |
|
||||
|
||||
### 6.2 结局判定流程
|
||||
|
||||
```
|
||||
最终 Boss 死亡时:
|
||||
|
||||
检查结局 C 条件(最严格)
|
||||
├─ 满足 → 触发结局 C
|
||||
└─ 不满足 →
|
||||
|
||||
检查结局 B 条件
|
||||
├─ 满足 → 触发结局 B
|
||||
└─ 不满足 → 触发结局 A
|
||||
|
||||
触发结局 X:
|
||||
→ 发出 OnEndingTriggered 事件(endingType)
|
||||
→ 播放对应过场动画序列
|
||||
→ 记录到 SaveData(endingUnlocked)
|
||||
→ 游戏结束流程
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 叙事事件目录
|
||||
|
||||
| 事件 | 触发时机 | 载荷 |
|
||||
|------|---------|------|
|
||||
| `OnDialogueStarted` | 开始对话 | `dialogueId, npcId` |
|
||||
| `OnDialogueNodeReached` | 到达对话节点 | `nodeId` |
|
||||
| `OnDialogueChoiceMade` | 玩家做出选择 | `choiceIndex, nextNodeId` |
|
||||
| `OnDialogueEnded` | 对话结束 | `dialogueId` |
|
||||
| `OnWorldFlagSet` | 世界标记变更 | `flagKey` |
|
||||
| `OnQuestStarted` | 任务开始 | `questId` |
|
||||
| `OnQuestAdvanced` | 任务推进 | `questId, newStage` |
|
||||
| `OnQuestCompleted` | 任务完成 | `questId` |
|
||||
| `OnEndingTriggered` | 结局触发 | `endingType` |
|
||||
| `OnCutsceneStarted` | 过场动画开始 | `cutsceneId` |
|
||||
| `OnCutsceneEnded` | 过场动画结束 | `cutsceneId` |
|
||||
70
Docs/DesignSpec/README.md
Normal file
70
Docs/DesignSpec/README.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# 泽灵(Zeling)· 系统设计规范文档集
|
||||
|
||||
> **定位**:本文档集是**引擎无关的系统设计规范**,描述游戏的功能需求、行为契约与数据模型。
|
||||
> **读者**:任何引擎的开发者、设计师、产品经理。
|
||||
> **不包含**:特定语言的代码、引擎插件名称、运行时 API 调用。
|
||||
> **区别于**:
|
||||
> - `Docs/Design/` — Unity 实现文档(与 Animancer、Cinemachine 等深度绑定)
|
||||
> - `Docs/Architecture/` — Unity 代码架构文档(asmdef、命名空间、Inspector)
|
||||
>
|
||||
> 本文档集可作为用任何引擎(Godot、Unreal、自研)重实现该游戏的**权威规范**。
|
||||
|
||||
---
|
||||
|
||||
## 导航索引
|
||||
|
||||
| 序号 | 文档 | 一句话描述 |
|
||||
|:----:|------|-----------|
|
||||
| — | **[设计规范与符号约定](./00_DesignConventions.md)** | 文档写法、数据类型符号、状态机符号、接口定义格式 |
|
||||
| 01 | [系统架构总览](./01_SystemArchitecture.md) | 设计哲学、系统全景图、模块边界、通信模式 |
|
||||
| 02 | [事件与消息系统](./02_EventMessaging.md) | 观察者模式约定、事件目录、发布/订阅契约 |
|
||||
| 03 | [玩家系统规范](./03_PlayerSystem.md) | 玩家实体构成、资源模型、状态机、输入契约 |
|
||||
| 04 | [战斗系统规范](./04_CombatSystem.md) | 伤害数据包、命中/受击管线、状态效果、连击 |
|
||||
| 05 | [移动系统规范](./05_MovementSystem.md) | 移动参数、跳跃模型、冲刺、墙壁力学 |
|
||||
| 06 | [形态系统规范](./06_FormSystem.md) | 三形态模型、切换契约、资源适配、武器联动 |
|
||||
| 07 | [敌人系统规范](./07_EnemySystem.md) | 敌人实体、AI 行为模型、Boss 系统、掉落 |
|
||||
| 08 | [世界系统规范](./08_WorldSystem.md) | 房间/场景模型、切换流程、存档点、可交互物 |
|
||||
| 09 | [进程系统规范](./09_ProgressionSystem.md) | 能力解锁、进度门控、Boss 进程、完成度 |
|
||||
| 10 | [UI 系统规范](./10_UISystem.md) | HUD 元素、屏幕状态机、数据绑定契约 |
|
||||
| 11 | [音频系统规范](./11_AudioSystem.md) | 自适应音乐分层、SFX 事件模型、音频区域 |
|
||||
| 12 | [经济系统规范](./12_EconomySystem.md) | 货币模型、商店契约、掉落模型、平衡参数 |
|
||||
| 13 | [存档系统规范](./13_SaveSystem.md) | 完整数据 Schema、存取契约、版本迁移 |
|
||||
| 14 | [叙事系统规范](./14_NarrativeSystem.md) | 故事节点、世界状态注册、NPC 对话版本 |
|
||||
|
||||
---
|
||||
|
||||
## 阅读建议
|
||||
|
||||
```
|
||||
入门阅读(了解全局):
|
||||
00_DesignConventions → 01_SystemArchitecture → 02_EventMessaging
|
||||
|
||||
核心玩法:
|
||||
03_PlayerSystem → 04_CombatSystem → 05_MovementSystem → 06_FormSystem
|
||||
|
||||
世界与敌人:
|
||||
07_EnemySystem → 08_WorldSystem → 09_ProgressionSystem
|
||||
|
||||
支撑系统:
|
||||
10_UISystem / 11_AudioSystem / 12_EconomySystem
|
||||
|
||||
持久化与叙事:
|
||||
13_SaveSystem / 14_NarrativeSystem
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 核心设计词汇表
|
||||
|
||||
| 术语 | 含义 |
|
||||
|------|------|
|
||||
| **系统(System)** | 一组紧密相关的行为和数据的逻辑单元,有明确输入/输出边界 |
|
||||
| **数据模型(Data Model)** | 描述一类信息的字段结构,不含行为逻辑 |
|
||||
| **行为契约(Behavioral Contract)** | 系统对外承诺的操作接口与结果保证 |
|
||||
| **事件(Event)** | 系统间一次性的状态通知,携带有限载荷 |
|
||||
| **配置数据(Config Data)** | 设计时填写、运行时只读的参数表 |
|
||||
| **运行时状态(Runtime State)** | 游戏运行中动态变化的数据 |
|
||||
| **门控(Gate)** | 要求玩家满足条件才能通过的进度锁 |
|
||||
| **形态(Form)** | 玩家可切换的战斗风格实例(天魂/地魂/命魂)|
|
||||
| **房间(Room)** | 游戏世界最小独立场景单元 |
|
||||
| **频道(Channel)** | 事件的具名发布通路,类型安全 |
|
||||
Reference in New Issue
Block a user