diff --git a/03_核心功能/UI/UI开发指南.md b/03_核心功能/UI/UI开发指南.md new file mode 100644 index 0000000..ea5efdd --- /dev/null +++ b/03_核心功能/UI/UI开发指南.md @@ -0,0 +1,154 @@ +# 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("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事件 | +| `OnOpen` | 每次打开 | 注册TC事件、刷新数据 | +| `OnClose` | 每次关闭 | 取消TC事件 | + +### 1.3 窗口操作 +```csharp +// 打开 +HFFunCatalogue.UIManager.OpenWindow(); +// 关闭 +HFFunCatalogue.UIManager.CloseWindow(); +``` + +--- + +## 二、事件绑定 + +| 事件类型 | 绑定位置 | 是否需要 `-=` | +|---------|---------|--------------| +| UI按钮/拖拽 | `OnRunAwake` | 不需要 | +| 全局TC事件 | `OnOpen`/`OnClose` | 需要 | + +--- + +## 三、常用组件 + +### 3.1 按钮 +```csharp +SFUI_Button btn = GetComponent(); +btn.OnAddClickListener += OnBtnClick; +btn.SetSelfGray(true); +``` + +### 3.2 文本 +```csharp +SFUI_TextMeshProUGUI txt = GetComponent(); +txt.text = "Hello"; +``` + +### 3.3 图片 +```csharp +SFUI_Image img = GetComponent(); +img.HFSetSprite(/* atlasName */, "Icon_Player", /* languageRoot */); +``` + +### 3.4 滚动列表(核心) +```csharp +SFUI_ScrollRect scroll = GetComponent(); +scroll.BindEvent( + () => itemList.Count, + (idx) => itemPrefab.gameObject, + OnUpdateItem, + (item) => item.gameObject.HFGetOrAddSimulateBehaviour() +); +scroll.ShowView(); +``` + +--- + +## 四、对象池 + +| 场景 | 推荐方式 | +|-----|---------| +| 滚动列表 | `SFUI_ScrollRect.BindEvent`(内置池) | +| 固定栏(装备/技能) | `HFSimulateBehaviourPool` | + +--- + +## 五、子组件 + +### 5.1 多态基类 +```csharp +public abstract class AbsListItem : AbsHFUIWindow +{ + protected SFUI_Button m_BtnItem; + protected Action m_OnSelect; + + protected override void OnRunAwake() + { + base.OnRunAwake(); + m_BtnItem = gameObject.GetComponent(); + m_BtnItem.OnAddClickListener += OnBtnClick; + } + + public virtual void SetData(T data, Action 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 +{ + protected override void OnDataChanged(CardData data) { } +} +``` + +--- + +## 六、开发规范 + +### 6.1 文件路径 +| 类型 | 路径 | +|-----|------| +| 脚本 | `Assets/Game/GameHFScripte/GameFunction/UIWindows/{Name}/` | +| 预制体 | `Assets/Game/GameHFResource/CN/UIWindows/{Name}/` | +| 图片 | `Assets/Game/GameHFResource/CN/SpriteAtlas/{Name}/` | + +### 6.2 性能优化 +- 使用对象池复用UI元素 +- 将图标打包到SpriteAtlas +- 滚动列表用 `SFUI_ScrollRect.BindEvent` + +--- + +**版本**: v1.0 +**适用**: StrayFog框架开发人员 \ No newline at end of file diff --git a/03_核心功能/UI/UI界面拼接设计指南.md b/03_核心功能/UI/UI界面拼接设计指南.md new file mode 100644 index 0000000..b7fe3cd --- /dev/null +++ b/03_核心功能/UI/UI界面拼接设计指南.md @@ -0,0 +1,167 @@ +# 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. **命名规范**:统一的命名规则便于维护和查找 + +--- + +**版本**: v1.0 +**适用**: StrayFog框架UI拼接开发人员 \ No newline at end of file diff --git a/03_核心功能/UI开发指南.md b/03_核心功能/UI开发指南.md deleted file mode 100644 index f7956e5..0000000 --- a/03_核心功能/UI开发指南.md +++ /dev/null @@ -1,352 +0,0 @@ -# StrayFog 框架 UI开发指南 - -## 一、UI窗口开发 - -### 1.1 窗口创建模板 - -```csharp -[HFAssetBundlePath(enHFLanguageRootFolder.ASSETS_GAME_GAMEHFRESOURCE, "UIWindows/MyWindow/MyWindow.prefab")] -[HFUIWindowLayer(enHFUICanvasLayer.UIWindow, enHFUIWindowLayer.Dynamic, isIgnoreCloseByESC = false)] -public class MyWindow : AbsHFUIWindow -{ - // UI组件 - private SFUI_Button BtnClose; - private SFUI_TextMeshProUGUI TxtTitle; - - protected override void OnRunAwake() - { - base.OnRunAwake(); - // 初始化UI组件引用 - BtnClose = FindUICtrlByName("BtnClose"); - TxtTitle = FindUICtrlByName("TxtTitle"); - - // 绑定按钮事件(OnRunAwake只执行一次) - BtnClose.OnAddClickListener += OnBtnClose; - } - - protected override void OnOpen(Action _onOpenComplete) - { - base.OnOpen(_onOpenComplete); - // 注册全局事件监听(每次打开都要注册) - HFFunCatalogue.Event.TCEvent.AddListener( - enHFCTCEvent.DataUpdate, OnDataUpdate); - - // 初始化数据显示 - RefreshUI(); - } - - protected override void OnClose(Action _onCloseComplete) - { - // 取消全局事件监听(每次关闭都要取消) - HFFunCatalogue.Event.TCEvent.RemoveListener( - enHFCTCEvent.DataUpdate, OnDataUpdate); - - base.OnClose(_onCloseComplete); - } - - private void OnBtnClose(GameObject go) => CloseWindow(); - private void OnDataUpdate(IHFEventArg arg) => RefreshUI(); - private void RefreshUI() { /* 更新UI显示 */ } -} -``` - -### 1.2 窗口生命周期 - -| 方法 | 调用时机 | 说明 | 推荐操作 | -|-----|---------|------|---------| -| `OnRunAwake` | 窗口创建时调用一次 | 初始化组件引用 | **绑定按钮事件、初始化对象池** | -| `OnRunStart` | OnRunAwake之后调用一次 | 初始化数据 | **配置数据加载** | -| `OnOpen` | 每次打开窗口时调用 | 注册事件、刷新数据 | **注册TC事件、初始化数据显示** | -| `OnClose` | 每次关闭窗口时调用 | 取消事件、清理资源 | **取消TC事件、回收对象池** | -| `OnDestroy` | 窗口销毁时调用 | 释放资源 | **释放非托管资源** | - -### 1.3 窗口操作 - -```csharp -// 打开窗口 -HFFunCatalogue.UIManager.OpenWindow(); - -// 打开窗口并获取实例 -HFFunCatalogue.UIManager.OpenWindow((win, args) => { - // win: 窗口实例 -}); - -// 关闭窗口 -HFFunCatalogue.UIManager.CloseWindow(); -``` - ---- - -## 二、事件绑定规范 - -### 2.1 事件绑定位置 - -| 事件类型 | 推荐位置 | 原因 | 是否需要 `-=` 防重复 | -|---------|---------|------|-------------------| -| **UI按钮事件** | `OnRunAwake` | 静态稳定,只需注册一次 | ❌ 不需要 | -| **列表拖拽事件** | `OnRunAwake` | 窗口生命周期内持续响应 | ❌ 不需要 | -| **全局TC事件** | `OnOpen`/`OnClose` | 窗口关闭后不应响应 | ✅ 需要 | -| **数据刷新逻辑** | `OnOpen` | 每次打开窗口需刷新 | - | - ---- - -## 三、常用UI组件 - -### 3.1 SFUI_Button组件 - -```csharp -SFUI_Button btn = GetComponent(); - -// 添加事件 -btn.OnAddClickListener += OnBtnClick; -btn.OnAddEnterListener += OnBtnEnter; -btn.OnAddExitListener += OnBtnExit; - -// 设置状态 -btn.SetSelfGray(true); // 灰色不可用 -btn.interactable = false; // 不可交互 -btn.SetSelected(true); // 选中状态 -``` - -### 3.2 SFUI_TextMeshProUGUI组件 - -```csharp -SFUI_TextMeshProUGUI txt = GetComponent(); - -txt.text = "Hello World"; -txt.color = Color.red; -txt.fontSize = 24; -txt.outlineColor = Color.black; -txt.outlineWidth = 2; - -// 动态调整高度 -txt.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, txt.preferredHeight); -``` - -### 3.3 SFUI_Image组件 - -```csharp -SFUI_Image img = GetComponent(); - -// 加载Sprite -img.HFSetSprite(enHFSpriteAtlas.ASSETS_GAME_GAMEHFRESOURCE_SPRITEATLAS_ITEM, - "Icon_Player", - enHFLanguageRootFolder.ASSETS_GAME_GAMEHFRESOURCE); - -// 设置透明度 -img.SetAlpha(0.5f); - -// 设置灰度 -img.SetSelfGray(true); - -// 清空Sprite -img.HFClearSprite(); -``` - -### 3.4 SFUI_ScrollRect组件(列表滚动) - -SFUI_ScrollRect 专门用于处理多物品的上下滑动列表,**内置对象池机制实现循环列表**,提供高效的列表渲染和滚动管理。 - -```csharp -SFUI_ScrollRect scroll = GetComponent(); - -// 绑定列表数据(核心方法) -scroll.BindEvent( - () => itemList.Count, // 数据数量 - (idx) => itemPrefab.gameObject, // 获取模板对象 - OnUpdateItem, // 更新回调 - (item) => item.gameObject.HFGetOrAddSimulateBehaviour() // 获取组件 -); - -// 刷新列表显示 -scroll.ShowView(); - -// 滚动到指定位置 -scroll.ScrollToIndex(0); // 滚动到第N项 -scroll.verticalNormalizedPosition = 0; // 滚动到底部(1=顶部,0=底部) -``` - -**BindEvent 参数说明**: - -| 参数 | 类型 | 说明 | -|-----|------|------| -| 1 | `Func` | 返回数据总数 | -| 2 | `Func` | 根据索引返回模板对象 | -| 3 | `Action` | 列表项更新回调 | -| 4 | `Func` | 获取列表项组件 | - -**更新回调示例**: -```csharp -private void OnUpdateItem(SFUI_ScrollRectItem _item) -{ - ItemSlot slot = _item.simulateBehaviour as ItemSlot; - ItemData data = itemList[_item.dataIdx]; - slot.SetData(data, OnItemClick); -} -``` - -**使用流程**: -1. 在 `OnRunAwake` 中调用 `BindEvent` 绑定数据 -2. 在 `OnOpen` 或数据更新时调用 `ShowView` 刷新显示 -3. 通过 `ScrollToIndex` 或 `verticalNormalizedPosition` 控制滚动位置 - -> **注意**:SFUI_ScrollRect 已内置对象池机制,**无需额外使用 HFSimulateBehaviourPool** 实现循环列表。 - ---- - -## 四、对象池模式 - -> **注意**:**循环滚动列表请使用 `SFUI_ScrollRect.BindEvent`**,HFSimulateBehaviourPool 适用于非滚动场景的对象复用。 - -### 4.1 对象池初始化 - -```csharp -HFSimulateBehaviourPool m_ItemPool = null; - -protected override void OnRunAwake() -{ - base.OnRunAwake(); - SFUI_Button itemPrefab = FindUICtrlByName("ItemPrefab"); - SFUI_Behaviour parentContainer = FindUICtrlByName("ParentContainer"); - - // 创建对象池 - m_ItemPool = new HFSimulateBehaviourPool( - itemPrefab.gameObject, // 模板对象 - parentContainer.gameObject // 父容器 - ); -} -``` - -### 4.2 对象池使用(适用于固定数量场景) - -```csharp -private void RefreshItems() -{ - // 回收所有已使用对象 - m_ItemPool.RecycUsingObject(); - - // 遍历数据创建新对象 - foreach (var data in itemDataList) - { - ItemSlot slot = m_ItemPool.GetItem(out bool isNew); - slot.SetData(data, OnItemClick); - } -} - -// 适用于固定数量的装备栏、技能栏等场景 -private void ShowEquipedCards() -{ - m_CardItems.RecycUsingObject(); - for (int i = 0; i < 5; i++) - { - var item = m_CardItems.GetItem(out bool isNew); - // 设置数据... - } -} -``` - -### 4.3 适用场景对比 - -| 场景 | 推荐方式 | 说明 | -|-----|---------|------| -| **滚动列表** | `SFUI_ScrollRect.BindEvent` | 自动实现循环复用 | -| **固定数量栏** | `HFSimulateBehaviourPool` | 如装备栏、技能栏(5个固定位置) | -| **动态弹窗** | `HFSimulateBehaviourPool` | 需要频繁创建销毁的弹窗 | - ---- - -## 五、子组件开发 - -子组件作为列表项使用,继承 `AbsHFUIWindow`,核心特点: - -| 特点 | 说明 | -|-----|------| -| **数据传递** | 通过 `SetData` 方法接收数据 | -| **回调机制** | 通过 `Action` 与父组件通信 | -| **对象池** | 配合 `HFSimulateBehaviourPool` 实现复用 | - ---- - -## 六、UI开发规范 - -### 6.1 文件放置结构 - -UI相关文件应按照以下规范组织: - -**脚本文件**(.cs): -``` -Assets/Game/GameHFScripte/GameFunction/UIWindows/ -├── BagWindow/ -│ └── BagWindow.cs # 窗口脚本 -├── MainWindow/ -│ └── MainWindow.cs -└── Common/ - └── ItemSlot.cs # 公共子组件脚本 -``` - -**预制体文件**(.prefab): -``` -Assets/Game/GameHFResource/CN/UIWindows/ -├── BagWindow/ -│ └── BagWindow.prefab # 窗口预制体 -├── MainWindow/ -│ └── MainWindow.prefab -└── Common/ - └── ItemSlot.prefab # 公共子组件预制体 -``` - -**图片资源**(按UI名称分类): -``` -Assets/Game/GameHFResource/CN/SpriteAtlas/ -├── BagWindow/ # 背包窗口相关图片 -│ ├── Icon_Bag.png -│ └── Btn_Close.png -├── MainWindow/ # 主窗口相关图片 -│ └── Btn_Menu.png -└── Common/ # 公共图片 - └── Btn_Confirm.png -``` - -### 6.2 窗口属性配置 - -每个窗口必须配置以下属性: - -```csharp -[HFAssetBundlePath(enHFLanguageRootFolder.ASSETS_GAME_GAMEHFRESOURCE, - "UIWindows/BagWindow/BagWindow.prefab")] -[HFUIWindowLayer(enHFUICanvasLayer.UIWindow, - enHFUIWindowLayer.Dynamic, - isIgnoreCloseByESC = false)] -public class BagWindow : AbsHFUIWindow -{ - // ... -} -``` - -**路径对应关系**: -- 属性路径:`UIWindows/BagWindow/BagWindow.prefab` -- 实际路径:`Assets/Game/GameHFResource/CN/UIWindows/BagWindow/BagWindow.prefab` - -**属性说明**: - -| 属性 | 作用 | 必填 | -|-----|------|------| -| `HFAssetBundlePath` | 指定预制体路径,用于资源加载 | ✅ | -| `HFUIWindowLayer` | 指定窗口层级和行为 | ✅ | -| `isIgnoreCloseByESC` | 是否忽略ESC关闭 | ❌ | - -### 6.3 性能优化建议 - -| 优化项 | 说明 | 实现方式 | -|-------|------|---------| -| **对象池复用** | 频繁创建的UI元素使用对象池 | 使用 `HFSimulateBehaviourPool` | -| **图集打包** | 将小图标打包到SpriteAtlas | 在Unity中配置SpriteAtlas | -| **层级优化** | 合理设置Canvas层级 | 使用 `HFUIWindowLayer` 属性 | -| **避免过度绘制** | 减少重叠UI元素 | 合理设计UI布局 | -| **批量操作** | 使用RectTransform批量修改 | 禁用后批量修改再启用 | -| **列表优化** | 使用SFUI_ScrollRect绑定模式 | 自动复用列表项 | - ---- - -**版本**: v1.0 -**适用范围**: StrayFog框架项目业务开发人员 \ No newline at end of file diff --git a/README.md b/README.md index 26d1fa5..f14a39d 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,10 @@ - [事件系统使用指南](03_核心功能/事件系统使用指南.md) - [资源管理使用指南](03_核心功能/资源管理使用指南.md) - [相机系统使用指南](03_核心功能/相机系统使用指南.md) -- [UI开发指南](03_核心功能/UI开发指南.md) - 窗口开发、组件使用、事件绑定、对象池、开发规范 + +#### UI相关 +- [UI开发指南](03_核心功能/UI/UI开发指南.md) - 窗口开发、组件使用、事件绑定、对象池、开发规范 +- [UI界面拼接设计指南](03_核心功能/UI/UI界面拼接设计指南.md) - 界面模块化设计、布局规划、模块组装 ### 04_开发流程 - [开发流程指南](04_开发流程/开发流程指南.md)