Files
zeling_v2/Docs/DesignSpec/00_DesignConventions.md
2026-05-08 11:04:00 +08:00

270 lines
8.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 通过事件通知 BB 不存在时 A 仍可正常运行 |
| **数据依赖**(只读配置)| A 读取共享配置数据,无运行时交互 |
---
## 8. 参数表格式
配置参数表统一格式:
| 参数名 | 类型 | 推荐值 | 说明 | 调整影响 |
|--------|------|--------|------|---------|
| `walkSpeed` | Number | 6.0 | 地面行走速度(单位/秒)| 越高越灵活,越低越沉重 |
| `jumpForce` | Number | 16.0 | 跳跃初速度 | 越高跳跃越高,需同步调整重力 |
> **调整原则**:每次只修改一个参数,实测手感后确认。参数间存在联动关系时,文档中注明。
---
## 9. 设计决策标注
文档中的设计决策用以下格式标注原因,方便日后回溯:
```
> **设计决策**[决策内容]
> **原因**[为什么这样设计]
> **替代方案**[考虑过但未选用的方案及原因]
```
### 示例
> **设计决策**:弹反成功后增加 +33 灵力,而非固定值
> **原因**:鼓励玩家主动弹反,弹反本身是高风险操作,大幅奖励使弹反策略具有可行的资源通路
> **替代方案**:弹反+0 灵力(纯战斗技巧),但测试发现玩家没有足够动机学习弹反
---
## 附:文档写作检查清单
在向本文档集新增或修改文档时,请确认:
- [ ] 所有数据类型使用抽象类型(不出现 `int`, `float`, `string`, `MonoBehaviour` 等)
- [ ] 所有引擎功能通过行为描述替代("物理检测地面"而非"OverlapBox"
- [ ] 系统接口以契约格式定义,不包含实现细节
- [ ] 参数表包含"调整影响"列
- [ ] 重要设计决策附有原因说明
- [ ] 文档末尾无悬空的"TODO"或临时注记