# 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=底部) ``` **使用流程**: 1. 在 `OnRunAwake` 中调用 `BindEvent` 绑定数据 2. 在 `OnOpen` 或数据更新时调用 `ShowView` 刷新显示 3. 通过 `ScrollToIndex` 或 `verticalNormalizedPosition` 控制滚动位置 --- ## 四、对象池模式 ### 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 OnItemClick(ItemData data) { // 处理点击逻辑 } ``` --- ## 五、子组件开发 子组件作为列表项使用,继承 `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框架项目业务开发人员