Files
pixelheros/.qoder/repowiki/zh/content/用户界面系统/用户界面系统.md
panw 4235e3b776 refactor(game): 移除已弃用的事件常量
- 删除 UpdateHero 和 UpdateFightHero 事件
- 移除 MISSION_UPDATE 事件常量
- 优化游戏事件枚举定义
2025-10-28 16:15:47 +08:00

16 KiB
Raw Blame History

用户界面系统

**本文档中引用的文件** - [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)

目录

  1. 简介
  2. 项目结构
  3. UI层级架构
  4. 核心组件分析
  5. MVVM框架集成
  6. 事件系统与数据绑定
  7. 使用示例
  8. 性能优化考虑
  9. 故障排除指南
  10. 总结

简介

本游戏采用基于Oops Framework的现代化UI系统架构集成了MVVM设计模式和事件驱动的组件化开发方式。系统通过GameUIConfig.ts统一管理界面配置支持多种UI层级和预制体路径配置并通过MVVM框架实现数据与视图的自动绑定。

项目结构

UI系统的核心文件组织结构如下

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

图表来源

章节来源

UI层级架构

层级类型定义

系统采用分层的UI管理架构通过LayerType枚举定义不同的界面层级

层级类型 描述 使用场景
UI层 主界面层级,常驻显示 英雄信息面板、顶部状态栏
PopUp层 弹出式界面 网络不稳定提示、Toast消息
Dialog层 模态对话框 弹窗界面、确认对话框

配置数据结构

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 : "管理"

图表来源

章节来源

核心组件分析

HInfoComp - 英雄信息面板

英雄信息面板是最复杂的UI组件负责展示和管理英雄选择、属性显示和交互功能。

组件架构

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 : "继承"

图表来源

英雄选择动画系统

组件实现了复杂的英雄选择动画系统,包括:

  • 循环滚动算法:支持无限循环的英雄选择
  • 平滑动画过渡使用Tween实现流畅的移动效果
  • 视觉焦点效果3号位置英雄显示1.5倍放大效果
  • 动画锁定机制:防止快速点击导致的动画冲突

数据绑定与更新

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 : 执行动画过渡

图表来源

章节来源

MInfoComp - 怪物信息组件

怪物信息组件负责显示当前关卡信息,采用简洁的设计模式。

组件特性

  • 事件驱动更新监听MISSION_UPDATE事件自动更新关卡信息
  • 文本绑定直接绑定到Label组件的字符串属性
  • 生命周期管理在onLoad中注册事件监听器在start中初始化数据

章节来源

TopComp - 顶部状态栏

顶部状态栏组件专注于显示玩家资源信息,特别是金币数量的动画效果。

特色功能

  • 资源动画效果:金币数量变化时触发缩放动画
  • 事件响应监听GOLD_UPDATE事件执行动画
  • 轻量级设计:专注于单一功能,避免过度复杂化

章节来源

VictoryComp - 胜利界面

胜利界面组件处理战斗结算和奖励展示,包含复杂的奖励系统和动画效果。

界面流程

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[返回主界面]

图表来源

章节来源

SIconComp - 技能图标组件

技能图标组件负责显示技能的视觉图标,采用简单的数据绑定模式。

组件特点

  • 资源动态加载根据技能UUID动态加载对应的图标资源
  • 路径配置通过SkillSet配置技能的资源路径
  • 轻量级实现:专注于单一职责,易于维护和扩展

章节来源

MVVM框架集成

架构概览

系统采用MVVMModel-View-ViewModel架构模式通过Oops Framework的ViewModel模块实现数据与视图的自动绑定。

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统一管理游戏数据特别是VM数据模型

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 : "管理"

图表来源

VMBase组件基类

所有UI组件都继承自VMBase组件实现自动的数据绑定功能

属性 类型 描述
watchPath string 需要监听的数据路径
watchPathArr string[] 多路径监听数组
templateMode boolean 启用模板模式
VM VMManager ViewModel管理器引用

章节来源

事件系统与数据绑定

事件类型定义

系统通过GameEvent枚举定义了完整的游戏事件体系

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

图表来源

数据绑定流程

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 : 响应用户交互

图表来源

章节来源

使用示例

注册新UI界面

以下是如何注册和使用新UI界面的完整示例

// 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);

处理按钮点击事件

// 在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("按钮被点击");
    }
}

实现动态数据刷新

// 使用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. 确认组件脚本是否正确注册

解决方案

// 检查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. 确认事件系统是否正常

解决方案

// 手动测试数据绑定
VM.setValue("global.test.value", "测试数据");
console.log("当前值:", VM.getValue("global.test.value"));

动画卡顿

问题症状UI动画播放不流畅

排查步骤

  1. 检查动画复杂度
  2. 验证硬件性能
  3. 确认动画队列管理

解决方案

// 优化动画实现
tween(target)
    .to(0.2, { position: newPosition })
    .call(() => {
        // 动画完成后清理
        this.cleanupAnimation();
    })
    .start();

章节来源

总结

本UI系统通过模块化的架构设计实现了高度可维护和可扩展的界面管理方案。系统的主要优势包括

  1. 统一的配置管理通过GameUIConfig.ts集中管理所有UI配置
  2. MVVM架构实现数据与视图的自动绑定减少手动DOM操作
  3. 事件驱动:基于事件系统实现松耦合的组件通信
  4. 性能优化:通过合理的架构设计和优化策略保证良好的性能表现
  5. 易于扩展模块化的设计使得添加新UI组件变得简单直观

该系统为游戏提供了稳定可靠的UI基础设施支持复杂的交互逻辑和动态内容更新是现代游戏开发中UI系统设计的优秀实践案例。