607 lines
16 KiB
Markdown
607 lines
16 KiB
Markdown
# 用户界面系统
|
||
|
||
<cite>
|
||
**本文档中引用的文件**
|
||
- [GameUIConfig.ts](file://assets/script/game/common/config/GameUIConfig.ts)
|
||
- [HInfoComp.ts](file://assets/script/game/map/HInfoComp.ts)
|
||
- [MInfoComp.ts](file://assets/script/game/map/MInfoComp.ts)
|
||
- [TopComp.ts](file://assets/script/game/map/TopComp.ts)
|
||
- [VictoryComp.ts](file://assets/script/game/map/VictoryComp.ts)
|
||
- [SIconComp.ts](file://assets/script/game/map/SIconComp.ts)
|
||
- [GameEvent.ts](file://assets/script/game/common/config/GameEvent.ts)
|
||
- [SingletonModuleComp.ts](file://assets/script/game/common/SingletonModuleComp.ts)
|
||
- [MvvmInfo.md](file://doc/mvvm/MvvmInfo.md)
|
||
- [VMBase.md](file://doc/mvvm/VMBase.md)
|
||
- [gui.md](file://doc/core/gui/gui.md)
|
||
</cite>
|
||
|
||
## 目录
|
||
1. [简介](#简介)
|
||
2. [项目结构](#项目结构)
|
||
3. [UI层级架构](#ui层级架构)
|
||
4. [核心组件分析](#核心组件分析)
|
||
5. [MVVM框架集成](#mvvm框架集成)
|
||
6. [事件系统与数据绑定](#事件系统与数据绑定)
|
||
7. [使用示例](#使用示例)
|
||
8. [性能优化考虑](#性能优化考虑)
|
||
9. [故障排除指南](#故障排除指南)
|
||
10. [总结](#总结)
|
||
|
||
## 简介
|
||
|
||
本游戏采用基于Oops Framework的现代化UI系统架构,集成了MVVM设计模式和事件驱动的组件化开发方式。系统通过GameUIConfig.ts统一管理界面配置,支持多种UI层级和预制体路径配置,并通过MVVM框架实现数据与视图的自动绑定。
|
||
|
||
## 项目结构
|
||
|
||
UI系统的核心文件组织结构如下:
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "UI配置层"
|
||
A[GameUIConfig.ts] --> B[UIID枚举]
|
||
A --> C[UIConfigData配置]
|
||
end
|
||
subgraph "组件层"
|
||
D[HInfoComp.ts] --> E[英雄信息面板]
|
||
F[MInfoComp.ts] --> G[怪物信息组件]
|
||
H[TopComp.ts] --> I[顶部状态栏]
|
||
J[VictoryComp.ts] --> K[胜利界面]
|
||
L[SIconComp.ts] --> M[技能图标组件]
|
||
end
|
||
subgraph "框架层"
|
||
N[MVVM框架] --> O[ViewModel]
|
||
N --> P[VMBase组件]
|
||
Q[事件系统] --> R[GameEvent]
|
||
end
|
||
A --> D
|
||
A --> F
|
||
A --> H
|
||
A --> J
|
||
A --> L
|
||
N --> D
|
||
N --> F
|
||
N --> H
|
||
N --> J
|
||
N --> L
|
||
Q --> D
|
||
Q --> F
|
||
Q --> H
|
||
Q --> J
|
||
Q --> L
|
||
```
|
||
|
||
**图表来源**
|
||
- [GameUIConfig.ts](file://assets/script/game/common/config/GameUIConfig.ts#L1-L36)
|
||
- [HInfoComp.ts](file://assets/script/game/map/HInfoComp.ts#L1-L344)
|
||
- [MInfoComp.ts](file://assets/script/game/map/MInfoComp.ts#L1-L28)
|
||
|
||
**章节来源**
|
||
- [GameUIConfig.ts](file://assets/script/game/common/config/GameUIConfig.ts#L1-L36)
|
||
- [HInfoComp.ts](file://assets/script/game/map/HInfoComp.ts#L1-L344)
|
||
|
||
## UI层级架构
|
||
|
||
### 层级类型定义
|
||
|
||
系统采用分层的UI管理架构,通过LayerType枚举定义不同的界面层级:
|
||
|
||
| 层级类型 | 描述 | 使用场景 |
|
||
|---------|------|----------|
|
||
| UI层 | 主界面层级,常驻显示 | 英雄信息面板、顶部状态栏 |
|
||
| PopUp层 | 弹出式界面 | 网络不稳定提示、Toast消息 |
|
||
| Dialog层 | 模态对话框 | 弹窗界面、确认对话框 |
|
||
|
||
### 配置数据结构
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class UIConfig {
|
||
+LayerType layer
|
||
+string prefab
|
||
+string bundle
|
||
}
|
||
class UIID {
|
||
<<enumeration>>
|
||
Loading
|
||
Netinstable
|
||
Role_Controller
|
||
Victory
|
||
Guide
|
||
}
|
||
class GameUIConfig {
|
||
+UIConfigData : {[key : number] : UIConfig}
|
||
+registerUI(id : number, config : UIConfig) : void
|
||
+getUIConfig(id : number) : UIConfig
|
||
}
|
||
UIID --> GameUIConfig : "配置"
|
||
UIConfig --> GameUIConfig : "管理"
|
||
```
|
||
|
||
**图表来源**
|
||
- [GameUIConfig.ts](file://assets/script/game/common/config/GameUIConfig.ts#L10-L35)
|
||
|
||
**章节来源**
|
||
- [GameUIConfig.ts](file://assets/script/game/common/config/GameUIConfig.ts#L1-L36)
|
||
|
||
## 核心组件分析
|
||
|
||
### HInfoComp - 英雄信息面板
|
||
|
||
英雄信息面板是最复杂的UI组件,负责展示和管理英雄选择、属性显示和交互功能。
|
||
|
||
#### 组件架构
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class HInfoComp {
|
||
+number h_uuid
|
||
+Node[] heroNodes
|
||
+Vec3 hero_pos
|
||
+boolean isMoving
|
||
+any moveTimeoutId
|
||
+update_data(uuid : number) : void
|
||
+load_all_hero(uuid : number) : void
|
||
+load_hui(uuid : number, pos_index : number) : Node
|
||
+next_hero() : void
|
||
+prev_hero() : void
|
||
+buy_hero() : void
|
||
+start_mission() : void
|
||
+moveHeroesLeft() : void
|
||
+moveHeroesRight() : void
|
||
+show_lock() : void
|
||
+claear_hero() : void
|
||
}
|
||
class CCComp {
|
||
+onLoad() : void
|
||
+start() : void
|
||
+update(deltaTime : number) : void
|
||
+reset() : void
|
||
}
|
||
HInfoComp --|> CCComp : "继承"
|
||
```
|
||
|
||
**图表来源**
|
||
- [HInfoComp.ts](file://assets/script/game/map/HInfoComp.ts#L10-L344)
|
||
|
||
#### 英雄选择动画系统
|
||
|
||
组件实现了复杂的英雄选择动画系统,包括:
|
||
|
||
- **循环滚动算法**:支持无限循环的英雄选择
|
||
- **平滑动画过渡**:使用Tween实现流畅的移动效果
|
||
- **视觉焦点效果**:3号位置英雄显示1.5倍放大效果
|
||
- **动画锁定机制**:防止快速点击导致的动画冲突
|
||
|
||
#### 数据绑定与更新
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant User as 用户
|
||
participant HInfo as HInfoComp
|
||
participant SM as SingletonModule
|
||
participant VM as ViewModel
|
||
User->>HInfo : 点击英雄选择
|
||
HInfo->>HInfo : 验证动画状态
|
||
HInfo->>HInfo : 计算下一个英雄
|
||
HInfo->>SM : updateFihgtHero(uuid)
|
||
SM->>VM : 更新战斗英雄
|
||
VM->>HInfo : 通知数据变更
|
||
HInfo->>HInfo : update_data(uuid)
|
||
HInfo->>HInfo : 执行动画过渡
|
||
```
|
||
|
||
**图表来源**
|
||
- [HInfoComp.ts](file://assets/script/game/map/HInfoComp.ts#L200-L344)
|
||
- [SingletonModuleComp.ts](file://assets/script/game/common/SingletonModuleComp.ts#L120-L140)
|
||
|
||
**章节来源**
|
||
- [HInfoComp.ts](file://assets/script/game/map/HInfoComp.ts#L1-L344)
|
||
|
||
### MInfoComp - 怪物信息组件
|
||
|
||
怪物信息组件负责显示当前关卡信息,采用简洁的设计模式。
|
||
|
||
#### 组件特性
|
||
|
||
- **事件驱动更新**:监听MISSION_UPDATE事件自动更新关卡信息
|
||
- **文本绑定**:直接绑定到Label组件的字符串属性
|
||
- **生命周期管理**:在onLoad中注册事件监听器,在start中初始化数据
|
||
|
||
**章节来源**
|
||
- [MInfoComp.ts](file://assets/script/game/map/MInfoComp.ts#L1-L28)
|
||
|
||
### TopComp - 顶部状态栏
|
||
|
||
顶部状态栏组件专注于显示玩家资源信息,特别是金币数量的动画效果。
|
||
|
||
#### 特色功能
|
||
|
||
- **资源动画效果**:金币数量变化时触发缩放动画
|
||
- **事件响应**:监听GOLD_UPDATE事件执行动画
|
||
- **轻量级设计**:专注于单一功能,避免过度复杂化
|
||
|
||
**章节来源**
|
||
- [TopComp.ts](file://assets/script/game/map/TopComp.ts#L1-L30)
|
||
|
||
### VictoryComp - 胜利界面
|
||
|
||
胜利界面组件处理战斗结算和奖励展示,包含复杂的奖励系统和动画效果。
|
||
|
||
#### 界面流程
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A[战斗胜利] --> B[显示胜利界面]
|
||
B --> C[展示奖励信息]
|
||
C --> D{玩家选择}
|
||
D --> |继续| E[下一关卡]
|
||
D --> |重新开始| F[重置关卡]
|
||
D --> |双倍奖励| G[观看广告]
|
||
E --> H[清理数据]
|
||
F --> H
|
||
G --> I[验证广告]
|
||
I --> J{验证结果}
|
||
J --> |成功| K[获得双倍奖励]
|
||
J --> |失败| L[显示错误]
|
||
K --> H
|
||
H --> M[返回主界面]
|
||
```
|
||
|
||
**图表来源**
|
||
- [VictoryComp.ts](file://assets/script/game/map/VictoryComp.ts#L30-L75)
|
||
|
||
**章节来源**
|
||
- [VictoryComp.ts](file://assets/script/game/map/VictoryComp.ts#L1-L75)
|
||
|
||
### SIconComp - 技能图标组件
|
||
|
||
技能图标组件负责显示技能的视觉图标,采用简单的数据绑定模式。
|
||
|
||
#### 组件特点
|
||
|
||
- **资源动态加载**:根据技能UUID动态加载对应的图标资源
|
||
- **路径配置**:通过SkillSet配置技能的资源路径
|
||
- **轻量级实现**:专注于单一职责,易于维护和扩展
|
||
|
||
**章节来源**
|
||
- [SIconComp.ts](file://assets/script/game/map/SIconComp.ts#L1-L28)
|
||
|
||
## MVVM框架集成
|
||
|
||
### 架构概览
|
||
|
||
系统采用MVVM(Model-View-ViewModel)架构模式,通过Oops Framework的ViewModel模块实现数据与视图的自动绑定。
|
||
|
||
```mermaid
|
||
graph LR
|
||
subgraph "Model层"
|
||
A[数据模型] --> B[SingletonModuleComp]
|
||
B --> C[vmdata对象]
|
||
end
|
||
subgraph "ViewModel层"
|
||
D[ViewModel] --> E[VMManager]
|
||
E --> F[数据监听]
|
||
end
|
||
subgraph "View层"
|
||
G[UI组件] --> H[VMBase组件]
|
||
H --> I[数据绑定]
|
||
end
|
||
C --> D
|
||
F --> H
|
||
I --> G
|
||
```
|
||
|
||
**图表来源**
|
||
- [SingletonModuleComp.ts](file://assets/script/game/common/SingletonModuleComp.ts#L50-L70)
|
||
- [MvvmInfo.md](file://doc/mvvm/MvvmInfo.md#L10-L15)
|
||
|
||
### 数据模型管理
|
||
|
||
系统通过SingletonModuleComp统一管理游戏数据,特别是VM数据模型:
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class SingletonModuleComp {
|
||
+vmdata : any
|
||
+vmAdd() : void
|
||
+updateGold(gold : number) : void
|
||
+updateFihgtHero(heroId : number) : void
|
||
+addHero(hero_uuid : number) : void
|
||
}
|
||
class ViewModel {
|
||
+add(data : any, tag : string) : void
|
||
+get(tag : string) : ViewModel
|
||
+setValue(path : string, value : any) : void
|
||
+getValue(path : string) : any
|
||
}
|
||
SingletonModuleComp --> ViewModel : "管理"
|
||
```
|
||
|
||
**图表来源**
|
||
- [SingletonModuleComp.ts](file://assets/script/game/common/SingletonModuleComp.ts#L50-L70)
|
||
|
||
### VMBase组件基类
|
||
|
||
所有UI组件都继承自VMBase组件,实现自动的数据绑定功能:
|
||
|
||
| 属性 | 类型 | 描述 |
|
||
|------|------|------|
|
||
| watchPath | string | 需要监听的数据路径 |
|
||
| watchPathArr | string[] | 多路径监听数组 |
|
||
| templateMode | boolean | 启用模板模式 |
|
||
| VM | VMManager | ViewModel管理器引用 |
|
||
|
||
**章节来源**
|
||
- [VMBase.md](file://doc/mvvm/VMBase.md#L1-L39)
|
||
|
||
## 事件系统与数据绑定
|
||
|
||
### 事件类型定义
|
||
|
||
系统通过GameEvent枚举定义了完整的游戏事件体系:
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "战斗事件"
|
||
A[FightStart] --> B[FightEnd]
|
||
C[FightPause] --> D[FightResume]
|
||
end
|
||
subgraph "关卡事件"
|
||
E[MissionStart] --> F[MissionEnd]
|
||
G[MissionWin] --> H[MissionLoss]
|
||
end
|
||
subgraph "资源事件"
|
||
I[GOLD_UPDATE] --> J[DIAMOND_UPDATE]
|
||
K[MEAT_UPDATE] --> L[MISSION_UPDATE]
|
||
end
|
||
subgraph "选择事件"
|
||
M[HeroSelect] --> N[EnhancementSelect]
|
||
O[TalentSelect] --> P[FuncSelect]
|
||
end
|
||
```
|
||
|
||
**图表来源**
|
||
- [GameEvent.ts](file://assets/script/game/common/config/GameEvent.ts#L10-L70)
|
||
|
||
### 数据绑定流程
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Model as 数据模型
|
||
participant VM as ViewModel
|
||
participant View as UI组件
|
||
participant Event as 事件系统
|
||
Model->>VM : 数据变更
|
||
VM->>VM : 触发监听器
|
||
VM->>Event : 发送事件通知
|
||
Event->>View : 分发事件
|
||
View->>View : 更新UI显示
|
||
View->>Model : 响应用户交互
|
||
```
|
||
|
||
**图表来源**
|
||
- [SingletonModuleComp.ts](file://assets/script/game/common/SingletonModuleComp.ts#L150-L195)
|
||
|
||
**章节来源**
|
||
- [GameEvent.ts](file://assets/script/game/common/config/GameEvent.ts#L1-L70)
|
||
- [SingletonModuleComp.ts](file://assets/script/game/common/SingletonModuleComp.ts#L150-L195)
|
||
|
||
## 使用示例
|
||
|
||
### 注册新UI界面
|
||
|
||
以下是如何注册和使用新UI界面的完整示例:
|
||
|
||
```typescript
|
||
// 1. 在GameUIConfig.ts中添加UI配置
|
||
export enum UIID {
|
||
// ... 现有UI ID
|
||
CustomPanel = 2001,
|
||
}
|
||
|
||
export var UIConfigData: { [key: number]: UIConfig } = {
|
||
// ... 现有UI配置
|
||
[UIID.CustomPanel]: {
|
||
layer: LayerType.UI,
|
||
prefab: "custom/prefab/panel"
|
||
},
|
||
};
|
||
|
||
// 2. 创建UI组件
|
||
@ccclass('CustomPanelComp')
|
||
export class CustomPanelComp extends CCComp {
|
||
protected onLoad(): void {
|
||
// 注册事件监听
|
||
oops.message.on(GameEvent.CustomEvent, this.onCustomEvent, this);
|
||
}
|
||
|
||
onCustomEvent(event: string, data: any): void {
|
||
// 处理自定义事件
|
||
this.updateDisplay(data);
|
||
}
|
||
|
||
updateDisplay(data: any): void {
|
||
// 更新UI显示
|
||
const label = this.node.getChildByName("content")
|
||
.getComponent(Label);
|
||
label.string = data.message;
|
||
}
|
||
}
|
||
|
||
// 3. 打开UI界面
|
||
const callbacks: UICallbacks = {
|
||
onAdded: (node: Node, params: any) => {
|
||
const comp = node.getComponent(CustomPanelComp);
|
||
// 初始化界面
|
||
},
|
||
onRemoved: (node: Node | null, params: any) => {
|
||
// 清理资源
|
||
}
|
||
};
|
||
|
||
oops.gui.open(UIID.CustomPanel, null, callbacks);
|
||
```
|
||
|
||
### 处理按钮点击事件
|
||
|
||
```typescript
|
||
// 在UI组件中处理按钮点击
|
||
@ccclass('ButtonHandler')
|
||
export class ButtonHandler extends Component {
|
||
start(): void {
|
||
// 获取按钮节点
|
||
const button = this.node.getChildByName("action_button");
|
||
if (button) {
|
||
// 添加点击事件监听
|
||
button.on(Node.EventType.TOUCH_END, this.onButtonClick, this);
|
||
}
|
||
}
|
||
|
||
onButtonClick(event: EventTouch): void {
|
||
// 触发游戏事件
|
||
oops.message.dispatchEvent(GameEvent.ButtonClicked, {
|
||
buttonId: "action_button",
|
||
timestamp: Date.now()
|
||
});
|
||
|
||
// 执行业务逻辑
|
||
this.performAction();
|
||
}
|
||
|
||
performAction(): void {
|
||
// 实现具体业务逻辑
|
||
console.log("按钮被点击");
|
||
}
|
||
}
|
||
```
|
||
|
||
### 实现动态数据刷新
|
||
|
||
```typescript
|
||
// 使用MVVM框架实现自动数据刷新
|
||
@ccclass('DynamicDataComp')
|
||
export class DynamicDataComp extends VMBase {
|
||
@property({ type: Label })
|
||
public displayLabel: Label = null!;
|
||
|
||
@property(String)
|
||
public watchPath: string = "global.player.health";
|
||
|
||
onValueChanged(newValue: any, oldValue: any, pathArray: string[]): void {
|
||
// 自动更新UI显示
|
||
this.displayLabel.string = `生命值: ${newValue}`;
|
||
|
||
// 可选:添加视觉反馈
|
||
if (newValue < oldValue) {
|
||
this.showDamageEffect();
|
||
}
|
||
}
|
||
|
||
showDamageEffect(): void {
|
||
// 显示伤害特效
|
||
tween(this.node)
|
||
.to(0.1, { color: Color.RED })
|
||
.to(0.1, { color: Color.WHITE })
|
||
.start();
|
||
}
|
||
}
|
||
```
|
||
|
||
## 性能优化考虑
|
||
|
||
### 组件复用策略
|
||
|
||
1. **预制体池化**:对于频繁创建销毁的UI组件,实现预制体池化机制
|
||
2. **延迟加载**:非关键UI组件采用延迟加载策略
|
||
3. **内存管理**:及时清理事件监听器和定时器
|
||
|
||
### 动画性能优化
|
||
|
||
1. **批量动画**:将多个动画合并为批量操作
|
||
2. **硬件加速**:利用CSS3变换实现硬件加速
|
||
3. **帧率控制**:限制动画帧率避免过度消耗CPU
|
||
|
||
### 数据绑定优化
|
||
|
||
1. **路径简化**:避免过深的数据绑定路径
|
||
2. **防抖处理**:对高频数据更新实施防抖机制
|
||
3. **选择性更新**:只更新发生变化的UI部分
|
||
|
||
## 故障排除指南
|
||
|
||
### 常见问题及解决方案
|
||
|
||
#### UI组件无法显示
|
||
|
||
**问题症状**:UI组件创建后不显示或显示异常
|
||
|
||
**排查步骤**:
|
||
1. 检查预制体路径配置是否正确
|
||
2. 验证UI层级设置是否符合预期
|
||
3. 确认组件脚本是否正确注册
|
||
|
||
**解决方案**:
|
||
```typescript
|
||
// 检查UI配置
|
||
console.log("UI配置:", UIConfigData[UIID.CustomPanel]);
|
||
|
||
// 验证预制体加载
|
||
oops.res.get(UIConfigData[UIID.CustomPanel].prefab, Prefab, (err, prefab) => {
|
||
if (err) {
|
||
console.error("预制体加载失败:", err);
|
||
}
|
||
});
|
||
```
|
||
|
||
#### 数据绑定失效
|
||
|
||
**问题症状**:数据更新后UI不自动刷新
|
||
|
||
**排查步骤**:
|
||
1. 检查watchPath路径是否正确
|
||
2. 验证ViewModel是否正常工作
|
||
3. 确认事件系统是否正常
|
||
|
||
**解决方案**:
|
||
```typescript
|
||
// 手动测试数据绑定
|
||
VM.setValue("global.test.value", "测试数据");
|
||
console.log("当前值:", VM.getValue("global.test.value"));
|
||
```
|
||
|
||
#### 动画卡顿
|
||
|
||
**问题症状**:UI动画播放不流畅
|
||
|
||
**排查步骤**:
|
||
1. 检查动画复杂度
|
||
2. 验证硬件性能
|
||
3. 确认动画队列管理
|
||
|
||
**解决方案**:
|
||
```typescript
|
||
// 优化动画实现
|
||
tween(target)
|
||
.to(0.2, { position: newPosition })
|
||
.call(() => {
|
||
// 动画完成后清理
|
||
this.cleanupAnimation();
|
||
})
|
||
.start();
|
||
```
|
||
|
||
**章节来源**
|
||
- [HInfoComp.ts](file://assets/script/game/map/HInfoComp.ts#L200-L344)
|
||
- [SingletonModuleComp.ts](file://assets/script/game/common/SingletonModuleComp.ts#L150-L195)
|
||
|
||
## 总结
|
||
|
||
本UI系统通过模块化的架构设计,实现了高度可维护和可扩展的界面管理方案。系统的主要优势包括:
|
||
|
||
1. **统一的配置管理**:通过GameUIConfig.ts集中管理所有UI配置
|
||
2. **MVVM架构**:实现数据与视图的自动绑定,减少手动DOM操作
|
||
3. **事件驱动**:基于事件系统实现松耦合的组件通信
|
||
4. **性能优化**:通过合理的架构设计和优化策略保证良好的性能表现
|
||
5. **易于扩展**:模块化的设计使得添加新UI组件变得简单直观
|
||
|
||
该系统为游戏提供了稳定可靠的UI基础设施,支持复杂的交互逻辑和动态内容更新,是现代游戏开发中UI系统设计的优秀实践案例。 |