[docs][refactor]: 将旧 01~06 中文教程合并整理为 modules/frameworks 文件夹结构

- 删除 01~05 旧中文教程目录
- 将 03 核心功能教程拆分为各 framework 模块的子文档
- 06 工具脚本移入 modules/frameworks/编辑器工具/UI工具/
- 非框架内容合并进 rules/20-开发规则.md 与 rules/40-工作流清单.md
- 更新所有交叉链接与文档关联表

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
lms
2026-07-07 18:36:15 +08:00
parent 5e5b9f8c80
commit ee1ff7f444
77 changed files with 6263 additions and 1133 deletions

View File

@@ -0,0 +1,129 @@
# UI 框架
## 分类
- 项目框架
## 目的
记录 UIWindow 管理、窗口基类、UIMono 桥接、窗口资源加载和 UI 生命周期。
## 已知线索
- 管理路径:`Assets/Game/GameHFScripte/CopyToHF/UIWindowMgr/`
- 窗口实现:`Assets/Game/GameHFScripte/GameFunction/UIWindows/`
- Mono 桥接:`Assets/Game/GameMono/Scripts/UIMono/`
- 资源路径:`Assets/Game/GameHFResource/CN/UIWindows/`
## 已确认链路
UI manager 初始化:
```text
HFUIWindowMgr.OnAfterCreateInstance()
-> OnInitializeCanvasAndCamera()
-> 为 enHFUICanvasLayer 创建 Canvas
-> 为 ScreenSpaceCamera Canvas 创建 UI Camera
-> 创建 CacheSiblingIndex Canvas
-> 创建或接管 EventSystem / StandaloneInputModule
```
打开窗口:
```text
HFFunCatalogue.UIManager.OpenWindow<T>()
-> HFUIWindowMgr.OnOpenWindow<HFUIWindowSetting>()
-> 创建 HFDefaultTask / HFUIWindow_RespondTask
-> 读取窗口类型上的 HFAssetBundlePathAttribute 和 HFUIWindowLayerAttribute
-> OnSettingWindowSiblingIndex()
-> 从缓存队列复用窗口实例,或 Activator.CreateInstance 创建窗口逻辑实例
-> OnPreloadWindowInMemory()
-> HFABMgr.Instance.LoadInMemory(windowPrefabPath)
-> win.BindGameObject(prefab)
-> OnAttachWindow(win)
-> win.SyncWindowState()
-> AbsHFUIWindow.OnOpen()
```
关闭窗口:
```text
CloseWindow<T>() / AbsHFUIWindow.CloseWindow()
-> HFUIWindowMgr.OnCloseWindow()
-> siblingIndexLayer.ToggleWindowActive(false)
-> 放入 mCacheWindowInstanceMaping
-> 处理 backtrack 自动恢复窗口
-> win.SyncWindowState()
-> AbsHFUIWindow.OnClose()
```
窗口资源绑定:
- 窗口类通过 `[HFAssetBundlePath(...)]` 标记 prefab 路径。
- 窗口类通过 `[HFUIWindowLayer(...)]` 标记 Canvas/Layer 和是否允许多开。
- `AbsHFUIWindowSetting.SetWindowType` 会读取上述 attribute生成 `winId``winTypeId` 和资源路径。
## 使用规则
- 新窗口必须继承 `AbsHFUIWindow`
- 新窗口必须配置 `HFAssetBundlePath``HFUIWindowLayer`
- 打开窗口统一走 `HFFunCatalogue.UIManager.OpenWindow<T>()`
- 关闭窗口统一走 `CloseWindow()``HFFunCatalogue.UIManager.CloseWindow<T>()`
-`OnOpen` 中注册的事件必须在 `OnClose` 中移除。
- 不直接 `Instantiate` / `Destroy` UI 窗口 prefab。
- 不绕过 `HFUIWindowMgr` 手动修改窗口 active、父节点或 siblingIndex。
- 普通业务窗口默认使用 `Dynamic`,提示类优先使用 `Tooltip`,强交互弹窗优先使用 `Popup``Highest` 仅用于明确的顶层兜底。
- UI prefab 放在 `Assets/Game/GameHFResource/<语言>/UIWindows/<模块>/`,代码中的 `HFAssetBundlePath` 使用相对 `UIWindows/...` 的路径。
- 优先使用项目已有 UIMono / ZYUGUI 绑定流程,不手写大量 `transform.Find`
- 列表、循环列表、网格优先使用已有 ZYUGUI / SuperScrollView 组件和编辑器转换工具。
- 异步加载或动画结束后再调用完成回调时,必须保证失败/取消路径不会卡住窗口状态。
## 新增 UI 窗口清单
1. 确认窗口所属功能模块。
2. 创建窗口类,继承 `AbsHFUIWindow`
3. 添加 `HFAssetBundlePath``HFUIWindowLayer`
4. 创建或更新 prefab。
5. 使用 UIMono / ZYUGUI 生成或绑定 UI 引用。
6.`HFFunCatalogue.UIManager.OpenWindow<T>()` 接入入口。
7.`OnOpen` / `OnClose` 对称处理事件、计时器、临时数据。
8. 验证打开、关闭、重复打开、切场景或语言变化时的表现。
9. 如果新增模块或改变 UI 架构,更新相关模块文档。
## 梳理任务
- [x] 梳理窗口基类和打开/关闭 API。
- [x] 梳理窗口 prefab 路径绑定方式。
- [ ] 梳理 UIMono 自动绑定和 partial 生成关系。
- [x] 梳理窗口生命周期Open/Close/状态同步。
- [x] 梳理 UI 事件订阅和释放规范。
- [x] 梳理功能 UI 和框架 UI 的边界。
## 待确认
- 常规入口已确认是 `HFFunCatalogue.UIManager` / `HFUIWindowMgr`,是否存在绕过路径待继续扫描。
- UI 资源会经过 `HFAssetBundlePathAttribute` 和语言路径规则,哪些 UI 真正有 CN/EN 差异待确认。
- UIMono 是否由编辑器工具生成。
- `OnOpen`/`OnClose` 外是否还有业务窗口统一订阅/释放规范待确认。
## 相关模块
- [资源框架](../资源管理/README.md)
- [事件框架](../事件系统/README.md)
- [ZYUGUI Tools](../../模块索引.md#编辑器工具)
---
## 文档关联
> 当本文档发生变更时,应同步检查以下关联文档,避免信息不一致。
| 文档 | 关联原因 |
|---|---|
| [modules/模块索引.md](../../模块索引.md) | ZYUGUI Tools |
| [modules/frameworks/事件系统/README.md](../事件系统/README.md) | 事件框架 |
| [modules/frameworks/资源管理/README.md](../资源管理/README.md) | 资源框架 |
| [rules/10-架构说明.md](../../../rules/10-架构说明.md) | 架构说明定义总体分层和依赖方向 |
| [rules/20-开发规则.md](../../../rules/20-开发规则.md) | 开发规则与框架/生成规则互相引用 |
| [rules/30-模块登记规则.md](../../../rules/30-模块登记规则.md) | 模块登记规则定义分类和状态口径 |
| TODO补充依赖或使用本框架的模块文档 | 如依赖本框架的功能模块 |

View File

@@ -0,0 +1,231 @@
# StrayFog 框架 UI 开发指南
## 一、窗口开发
### 1.1 创建模板
```csharp
[HFAssetBundlePath(enHFLanguageRootFolder.ASSETS_GAME_GAMEHFRESOURCE, "UIWindows/MyWindow/MyWindow.prefab")]
[HFUIWindowLayer(enHFUICanvasLayer.UIWindow, enHFUIWindowLayer.Dynamic)]
public class MyWindow : AbsHFUIWindow
{
private SFUI_Button BtnClose;
protected override void OnRunAwake()
{
base.OnRunAwake();
BtnClose = FindUICtrlByName<SFUI_Button>("BtnClose");
BtnClose.OnAddClickListener += OnBtnClose;
}
protected override void OnOpen(Action _onOpenComplete)
{
base.OnOpen(_onOpenComplete);
RefreshUI();
}
private void OnBtnClose(GameObject go) => CloseWindow();
private void RefreshUI() { }
}
```
### 1.2 生命周期
| 方法 | 调用时机 | 推荐操作 |
|-----|---------|---------|
| `OnRunAwake` | 创建时一次 | 绑定 UI 事件、初始化滚动列表 `BindEvent` |
| `OnOpen` | 每次打开 | 注册 TC 事件、调用 `ShowView()` 刷新数据 |
| `OnClose` | 每次关闭 | 取消 TC 事件 |
**关键原则**
- **绑定类操作**(如 `BindEvent`)放在 `OnRunAwake`,只需执行一次
- **刷新类操作**(如 `ShowView`)放在 `OnOpen`,每次打开都需执行
### 1.3 窗口操作
```csharp
// 打开
HFFunCatalogue.UIManager.OpenWindow<MyWindow>();
// 关闭
HFFunCatalogue.UIManager.CloseWindow<MyWindow>();
```
---
## 二、事件绑定
| 事件类型 | 绑定位置 | 是否需要 `-=` |
|---------|---------|--------------|
| UI 按钮/拖拽 | `OnRunAwake` | 不需要 |
| 全局 TC 事件 | `OnOpen`/`OnClose` | 需要 |
---
## 三、常用组件
### 3.1 按钮
```csharp
SFUI_Button btn = GetComponent<SFUI_Button>();
btn.OnAddClickListener += OnBtnClick;
btn.SetSelfGray(true);
```
### 3.2 文本
```csharp
SFUI_TextMeshProUGUI txt = GetComponent<SFUI_TextMeshProUGUI>();
txt.text = "Hello";
```
### 3.3 图片
```csharp
SFUI_Image img = GetComponent<SFUI_Image>();
img.HFSetSprite(/* atlasName */, "Icon_Player", /* languageRoot */);
```
### 3.4 滚动列表(核心)
**生命周期正确划分示例**
```csharp
private SFUI_ScrollRect m_ScrollList;
private List<ItemData> m_ItemList;
protected override void OnRunAwake()
{
base.OnRunAwake();
m_ScrollList = FindUICtrlByName<SFUI_ScrollRect>("ScrollList");
// ✅ 绑定事件放在 Awake一次绑定永久生效
m_ScrollList.BindEvent(
() => m_ItemList.Count, // 数据源闭包
(idx) => itemPrefab.gameObject, // 生成预制体
OnUpdateItem, // 更新回调
(item) => item.gameObject.HFGetOrAddSimulateBehaviour<ItemSlot>() // 获取组件
);
}
protected override void OnOpen(Action _onOpenComplete)
{
base.OnOpen(_onOpenComplete);
m_ItemList = GetDataFromServer(); // 获取最新数据
m_ScrollList.ShowView(); // ✅ 刷新显示放在 Open
}
private void OnUpdateItem(int index, AbsHFUIWindow window)
{
ItemSlot slot = window as ItemSlot;
slot.SetData(m_ItemList[index]);
}
```
**设计要点**
- `BindEvent``OnRunAwake` 中执行,建立绑定机制
- `ShowView``OnOpen` 中执行,触发数据刷新
- 数据源通过闭包引用,`ShowView` 时自动获取最新数据
---
## 四、对象池
| 场景 | 推荐方式 |
|-----|---------|
| 滚动列表 | `SFUI_ScrollRect.BindEvent`(内置池) |
| 固定栏(装备/技能) | `HFSimulateBehaviourPool<T>` |
---
## 五、子组件
### 5.1 多态基类
```csharp
public abstract class AbsListItem<T> : AbsHFUIWindow
{
protected SFUI_Button m_BtnItem;
protected Action<T> m_OnSelect;
protected override void OnRunAwake()
{
base.OnRunAwake();
m_BtnItem = gameObject.GetComponent<SFUI_Button>();
m_BtnItem.OnAddClickListener += OnBtnClick;
}
public virtual void SetData(T data, Action<T> onSelect = null)
{
m_OnSelect = onSelect;
OnDataChanged(data);
}
protected abstract void OnDataChanged(T data);
private void OnBtnClick(GameObject go) => m_OnSelect?.Invoke(m_CurrentData);
}
// 子类
public class CardItem : AbsListItem<CardData>
{
protected override void OnDataChanged(CardData data) { }
}
```
---
## 六、开发规范
### 6.1 文件路径
#### 6.1.1 核心资源路径
| 类型 | 路径 | 说明 |
|-----|------|------|
| **窗口脚本** | `Assets/Game/GameHFScripte/GameFunction/UIWindows/{WindowName}/` | 窗口逻辑脚本存放目录 |
| **窗口预制体** | `Assets/Game/GameHFResource/CN/UIWindows/{WindowName}/` | UI 窗口预制体存放目录 |
| **图标图集** | `Assets/Game/GameHFResource/CN/SpriteAtlas/{AtlasName}/` | SpriteAtlas 图集资源 |
| **字体资源** | `Assets/Game/GameHFResource/CN/Fonts/` | 字体文件存放目录 |
#### 6.1.2 工具脚本路径
| 工具名称 | 路径 | 职责 |
|---------|------|------|
| **UIPrefabGenerator** | `Assets/Editor/Command/UIPrefabGenerator.cs` | JSON 转 UI 预制体 |
| **UIPrefabToJson** | `Assets/Editor/Command/UIPrefabToJson.cs` | 预制体转 JSON |
| **RemoteCommand** | `Assets/Editor/Command/RemoteCommand.cs` | 外部命令接口 |
| **ExternalCommandListener** | `Assets/Editor/Command/ExternalCommandListener.cs` | 外部命令监听器 |
#### 6.1.3 文档路径
| 文档名称 | 路径 |
|---------|------|
| UI 开发指南 | [UI窗口系统/开发指南.md](开发指南.md) |
| UI 界面拼接设计指南 | [UI窗口系统/界面拼接.md](界面拼接.md) |
#### 6.1.4 命令触发路径
- **触发文件**: `{ProjectRoot}/Trigger_Command.txt`
- **JSON 配置**: `Assets/Editor/UI/{WindowName}.json`
### 6.2 性能优化
- 使用对象池复用 UI 元素
- 将图标打包到 SpriteAtlas
- 滚动列表用 `SFUI_ScrollRect.BindEvent`
---
**版本**: v1.1
**适用**: StrayFog 框架 UI 开发人员
---
## 文档关联
> 当本文档发生变更时,应同步检查以下关联文档,避免信息不一致。
| 文档 | 关联原因 |
|---|---|
| [UI 窗口系统入口](README.md) | 本文件是 UI 窗口系统模块的子文档 |
| [UI 界面拼接设计指南](界面拼接.md) | 界面拼接是 UI 开发的补充设计指南 |
| [UI 拼接工具](../编辑器工具/UI拼接工具.md) | JSON 驱动 UI 生成工具说明 |
| [事件系统](../事件系统/README.md) | UI 事件订阅和释放规范 |
| [对象池与运行时对象管理](../内存对象管理/README.md) | UI 元素复用相关 |
| [资源管理](../资源管理/README.md) | UI 资源加载依赖资源管理 |
| [modules/模块索引.md](../../模块索引.md) | 模块索引是项目知识总入口 |
| [rules/10-架构说明.md](../../../rules/10-架构说明.md) | 架构说明定义总体分层和依赖方向 |
| [rules/20-开发规则.md](../../../rules/20-开发规则.md) | UI 命名与编码规范互相引用 |
| [rules/30-模块登记规则.md](../../../rules/30-模块登记规则.md) | 模块登记规则定义分类和状态口径 |

View File

@@ -0,0 +1,192 @@
# UI 界面拼接设计指南
## 一、界面结构设计原则
### 1.1 模块化拆分
将界面按功能划分为独立模块:
| 模块类型 | 功能定位 | 示例 |
|---------|---------|------|
| **信息展示区** | 显示玩家状态、资源等静态信息 | 顶部信息栏、左侧状态栏 |
| **功能入口区** | 提供功能按钮入口 | 中央功能区、底部快捷栏 |
| **交互面板区** | 可展开/收起的功能面板 | 右侧功能面板、顶部按钮区 |
| **输入输出区** | 用户输入和系统反馈 | 聊天输入框、提示信息 |
### 1.2 经典布局模式
```
┌─────────────────────────────────────────────────────┐
│ TopArea (信息展示 + 可收起功能按钮) │
├──────────┬───────────────────────┬──────────────────┤
│ Left │ │ Right │
│ Area │ CenterArea │ Area │
│ (状态) │ (核心功能入口) │ (功能面板) │
│ │ │ │
├──────────┴───────────────────────┴──────────────────┤
│ BottomArea (快捷功能 + 状态信息 + 输入) │
└─────────────────────────────────────────────────────┘
```
---
## 二、组件拆分方法
### 2.1 基础组件识别
| 组件类型 | 识别特征 | 处理方式 |
|---------|---------|---------|
| **按钮** | 可点击、有交互反馈 | 使用 `SFUI_Button` |
| **文本** | 静态/动态文字显示 | 使用 `SFUI_TextMeshProUGUI` |
| **图片** | 图标、背景图 | 使用 `SFUI_Image` |
| **进度条** | HP、MP、经验等 | 使用 `SFUI_Slider` |
| **列表** | 可滚动的项目列表 | 使用 `SFUI_ScrollRect` |
### 2.2 复合组件封装
将功能相关的基础组件组合为复合组件,便于复用和维护:
**设计原则**
- 将同一功能模块的组件封装在一起(如玩家头像+血条+蓝条)
- 提供统一的数据设置接口
- 保持组件之间的逻辑独立性
---
## 三、预制体层级规范
### 3.1 标准层级结构
```
WindowName (RectTransform)
├── ModuleName (RectTransform) # 模块容器
│ ├── ComponentName (SFUI_*) # 功能组件
│ ├── SubModule (RectTransform) # 子模块
│ └── CollapsibleArea (RectTransform) # 可收起区域
└── BtnCollapse (SFUI_Button) # 收起控制按钮
```
### 3.2 命名规范
| 类型 | 命名规则 | 示例 |
|-----|---------|------|
| 模块容器 | PascalCase + Area | `TopArea` |
| 功能组件 | PascalCase | `BtnCollapseTop` |
| 可收起区域 | PascalCase + FuncArea | `TopFuncArea` |
| 状态变量 | m_ + PascalCase | `m_IsTopCollapsed` |
---
## 四、收起/展开功能设计
### 4.1 功能定义
| 按钮 | 控制区域 | 用途 |
|-----|---------|------|
| `BtnCollapseTop` | 顶部功能按钮区 | 收起/展开顶部按钮群 |
| `BtnCollapseRight` | 右侧功能面板区 | 收起/展开右侧功能面板 |
### 4.2 设计要点
**状态管理**:每个可收起区域需要一个布尔状态变量来记录当前收起/展开状态。
**交互逻辑**
1. 点击收起按钮时,切换对应区域的显示/隐藏状态
2. 同时切换按钮图标(收起时显示展开图标,展开时显示收起图标)
**布局要求**
- 收起按钮应放置在对应区域的边缘位置,便于用户找到
- 收起区域内的所有元素应作为一个整体进行显示/隐藏控制
- 收起状态应在窗口生命周期内保持记忆
---
## 五、实际案例:主界面拼接
### 5.1 模块化设计思想
**核心原则**:将界面按功能边界划分为独立模块,模块内可嵌套子模块。
**模块归类方法**
1. **一级模块**:按空间位置划分(顶部、左侧、中央、右侧、底部)
2. **二级模块**:按功能类型划分(信息展示区、功能按钮区、输入输出区)
3. **三级模块**:按具体功能划分(玩家头像、资源显示、功能按钮群)
**层级关系示例**
```
Window
├── TopArea (一级:位置)
│ ├── InfoPanel (二级:信息展示)
│ │ └── TxtWelcome (三级:具体组件)
│ └── FuncButtons (二级:功能按钮)
│ └── BtnUpload (三级:具体按钮)
└── LeftArea (一级:位置)
└── PlayerPortrait (二级:复合组件)
├── ImgAvatar (三级:头像)
└── BarHP (三级:血条)
```
**设计要点**
- 同一功能域内的元素归为同一模块(如头像、血条、蓝条归为玩家状态模块)
- 独立交互功能作为独立模块(如收起按钮单独作为控制模块)
- 可收起区域作为独立子模块,便于统一控制显示/隐藏
---
## 六、界面拼接流程
### 6.1 设计阶段
1. **需求分析**:明确界面功能和交互需求
2. **模块划分**:将界面拆分为独立功能模块
3. **层级设计**:设计预制体层级结构
### 6.2 开发阶段
1. **组件创建**:创建基础组件和复合组件
2. **预制体搭建**:按层级结构搭建预制体
3. **脚本编写**:实现交互逻辑和收起/展开功能
### 6.3 测试阶段
1. **功能测试**:验证所有按钮和交互功能
2. **收起测试**:测试收起/展开功能正常工作
3. **适配测试**:验证不同分辨率下的显示效果
---
## 七、注意事项
1. **组件复用**:相同功能的组件尽量复用,减少冗余
2. **状态管理**:收起状态需要正确保存和恢复
3. **图标反馈**:收起按钮图标应随状态变化
4. **性能优化**:可收起区域使用 `SetActive` 而非销毁重建
5. **命名规范**:统一的命名规则便于维护和查找
---
## 八、JSON 配置驱动的 UI 生成方式
本项目支持通过 JSON 配置快速生成 UI 预制体,详细工具说明、命令格式和部署步骤见 [UI 拼接工具](../编辑器工具/UI拼接工具.md)。
UI 相关人员核心工作流程:读取设计效果图和碎片图片,生成 JSON 配置文件,再通过工具自动生成 Unity 预制体。
---
**版本**: v1.2
**适用**: StrayFog 框架 UI 拼接开发人员
---
## 文档关联
> 当本文档发生变更时,应同步检查以下关联文档,避免信息不一致。
| 文档 | 关联原因 |
|---|---|
| [UI 窗口系统入口](README.md) | 本文件是 UI 窗口系统模块的子文档 |
| [UI 开发指南](开发指南.md) | 窗口开发与界面拼接互相补充 |
| [UI 拼接工具](../编辑器工具/UI拼接工具.md) | JSON 驱动 UI 生成工具说明 |
| [modules/模块索引.md](../../模块索引.md) | 模块索引是项目知识总入口 |
| [rules/10-架构说明.md](../../../rules/10-架构说明.md) | 架构说明定义总体分层和依赖方向 |
| [rules/20-开发规则.md](../../../rules/20-开发规则.md) | UI 命名与资源规则互相引用 |
| [rules/30-模块登记规则.md](../../../rules/30-模块登记规则.md) | 模块登记规则定义分类和状态口径 |