Files
UnityAI/03_核心功能/UI开发指南.md

315 lines
9.0 KiB
Markdown
Raw 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.
# 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<SFUI_Button>("BtnClose");
TxtTitle = FindUICtrlByName<SFUI_TextMeshProUGUI>("TxtTitle");
// 绑定按钮事件OnRunAwake只执行一次
BtnClose.OnAddClickListener += OnBtnClose;
}
protected override void OnOpen(Action _onOpenComplete)
{
base.OnOpen(_onOpenComplete);
// 注册全局事件监听(每次打开都要注册)
HFFunCatalogue.Event.TCEvent.AddListener<HFEvent_DataUpdate>(
enHFCTCEvent.DataUpdate, OnDataUpdate);
// 初始化数据显示
RefreshUI();
}
protected override void OnClose(Action _onCloseComplete)
{
// 取消全局事件监听(每次关闭都要取消)
HFFunCatalogue.Event.TCEvent.RemoveListener<HFEvent_DataUpdate>(
enHFCTCEvent.DataUpdate, OnDataUpdate);
base.OnClose(_onCloseComplete);
}
private void OnBtnClose(GameObject go) => CloseWindow();
private void OnDataUpdate(IHFEventArg<enHFCTCEvent> arg) => RefreshUI();
private void RefreshUI() { /* 更新UI显示 */ }
}
```
### 1.2 窗口生命周期
| 方法 | 调用时机 | 说明 | 推荐操作 |
|-----|---------|------|---------|
| `OnRunAwake` | 窗口创建时调用一次 | 初始化组件引用 | **绑定按钮事件、初始化对象池** |
| `OnRunStart` | OnRunAwake之后调用一次 | 初始化数据 | **配置数据加载** |
| `OnOpen` | 每次打开窗口时调用 | 注册事件、刷新数据 | **注册TC事件、初始化数据显示** |
| `OnClose` | 每次关闭窗口时调用 | 取消事件、清理资源 | **取消TC事件、回收对象池** |
| `OnDestroy` | 窗口销毁时调用 | 释放资源 | **释放非托管资源** |
### 1.3 窗口操作
```csharp
// 打开窗口
HFFunCatalogue.UIManager.OpenWindow<MyWindow>();
// 打开窗口并获取实例
HFFunCatalogue.UIManager.OpenWindow<MyWindow>((win, args) => {
// win: 窗口实例
});
// 关闭窗口
HFFunCatalogue.UIManager.CloseWindow<MyWindow>();
```
---
## 二、事件绑定规范
### 2.1 事件绑定位置
| 事件类型 | 推荐位置 | 原因 | 是否需要 `-=` 防重复 |
|---------|---------|------|-------------------|
| **UI按钮事件** | `OnRunAwake` | 静态稳定,只需注册一次 | ❌ 不需要 |
| **列表拖拽事件** | `OnRunAwake` | 窗口生命周期内持续响应 | ❌ 不需要 |
| **全局TC事件** | `OnOpen`/`OnClose` | 窗口关闭后不应响应 | ✅ 需要 |
| **数据刷新逻辑** | `OnOpen` | 每次打开窗口需刷新 | - |
---
## 三、常用UI组件
### 3.1 SFUI_Button组件
```csharp
SFUI_Button btn = GetComponent<SFUI_Button>();
// 添加事件
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<SFUI_TextMeshProUGUI>();
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<SFUI_Image>();
// 加载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<SFUI_ScrollRect>();
// 绑定列表数据(核心方法)
scroll.BindEvent(
() => itemList.Count, // 数据数量
(idx) => itemPrefab.gameObject, // 获取模板对象
OnUpdateItem, // 更新回调
(item) => item.gameObject.HFGetOrAddSimulateBehaviour<ItemSlot>() // 获取组件
);
// 刷新列表显示
scroll.ShowView();
// 滚动到指定位置
scroll.ScrollToIndex(0); // 滚动到第N项
scroll.verticalNormalizedPosition = 0; // 滚动到底部1=顶部0=底部)
```
**使用流程**
1.`OnRunAwake` 中调用 `BindEvent` 绑定数据
2.`OnOpen` 或数据更新时调用 `ShowView` 刷新显示
3. 通过 `ScrollToIndex``verticalNormalizedPosition` 控制滚动位置
---
## 四、对象池模式
### 4.1 对象池初始化
```csharp
HFSimulateBehaviourPool<ItemSlot> m_ItemPool = null;
protected override void OnRunAwake()
{
base.OnRunAwake();
SFUI_Button itemPrefab = FindUICtrlByName<SFUI_Button>("ItemPrefab");
SFUI_Behaviour parentContainer = FindUICtrlByName<SFUI_Behaviour>("ParentContainer");
// 创建对象池
m_ItemPool = new HFSimulateBehaviourPool<ItemSlot>(
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<T>` 与父组件通信 |
| **对象池** | 配合 `HFSimulateBehaviourPool<T>` 实现复用 |
---
## 六、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<T>` |
| **图集打包** | 将小图标打包到SpriteAtlas | 在Unity中配置SpriteAtlas |
| **层级优化** | 合理设置Canvas层级 | 使用 `HFUIWindowLayer` 属性 |
| **避免过度绘制** | 减少重叠UI元素 | 合理设计UI布局 |
| **批量操作** | 使用RectTransform批量修改 | 禁用后批量修改再启用 |
| **列表优化** | 使用SFUI_ScrollRect绑定模式 | 自动复用列表项 |
---
**版本**: v1.0
**适用范围**: StrayFog框架项目业务开发人员