在游戏UI开发中,红点系统虽然逻辑简单,但随着功能模块的膨胀,极易产生"面条代码"。为了解决耦合与维护难题,我们采用 MV(Model-View)数据视图分离 结合 全局单例管理 的架构方案。
本方案不依赖特定引擎,核心在于理清数据流向与职责边界。
核心架构脑图
在设计之初,我们需要明确系统的层级关系。整个红点系统可以拆解为以下模块:

1. 类结构设计 (UML Class Diagram)
为了更直观地展示各模块间的依赖关系,我们使用 UML 类图来描述。
- RedDotManager:系统的核心控制者,持有所有数据。
- RedDotModel:纯粹的数据载体,负责通知。
- RedDotItem:UI 表现层,依赖 Model 进行更新。

2. 模块详细设计
2.1 红点全局集中管理 (Manager)
Manager 是数据的唯一真理来源(Single Source of Truth)。
- 单例模式:确保全局只有一个数据中心,避免状态冲突。
- 数据字典 :使用
Key-Value结构存储,Key 为红点类型枚举,Value 为对应的 Model 实例。 - 惰性获取 (Lazy Get) :
- 调用
GetRedDotModel时,先检查字典。 - 若不存在,则
new一个新的 Model 加入字典并返回。 - 优势:无需在项目启动时手动注册所有红点,按需创建,节省内存。
- 调用
- 状态设置与广播 :
- 提供
SetRedDotState方法。 - 修改 Model 中的布尔值后,立即调用 Model 的
NotifyUpdate方法触发事件。
- 提供
2.2 数据模型 (Model)
Model 层完全独立于 UI,只负责数据的存储和变更通知。
- 红点类型枚举:标识该数据属于哪个功能模块。
- 显示状态 (bool) :核心数据,决定红点是
Active还是Inactive。 - 事件通知机制 :
- 提供一个公开的事件接口(如 Action, Delegate, Signal 等)。
- 当数据发生变化时,遍历并执行所有订阅者的回调。
2.3 红点 Item 预制体 (View)
View 层是挂载在具体 UI 节点上的组件,负责"看"和"做"。
- 配置化 :
- 提供一个公开字段,允许在编辑器/配置表中手动选择该 UI 对应的 红点类型枚举。
- 初始化 (Init) :
- 在生命周期开始时(如
Awake或OnEnable),根据配置的枚举,向 Manager 请求对应的 Model。 - 绑定事件:将自身的刷新方法注册到 Model 的事件通知上。
- 在生命周期开始时(如
- 视图更新逻辑 :
- 当收到 Model 的广播时,读取 Model 的
bool值。 - 直接控制 UI 节点(GameObject/Image)的
SetActive或Visible属性。
- 当收到 Model 的广播时,读取 Model 的
- 资源释放 :
- 在销毁时(
OnDestroy或OnDisable),务必取消事件订阅,防止内存泄漏。
- 在销毁时(
3. 数据流向总结
为了便于理解,我们可以用简单的流程图概括一次红点触发的全过程:
- 业务触发 :玩家获得道具 -> 调用
Manager.SetRedDotState(Bag, true)。 - 数据更新 :Manager 找到
Bag对应的 Model -> 修改isActive = true。 - 事件广播 :Model 执行
NotifyUpdate()-> 触发所有绑定的回调。 - 视图响应 :所有挂载了
Bag类型红点的 UI 组件收到回调 -> 执行SetActive(true)-> 红点亮起。
4. 方案优势
- 彻底解耦:UI 预制体不需要知道业务逻辑(为什么亮),业务逻辑也不需要知道有哪些 UI(哪里亮)。
- 高复用性:红点 Item 预制体可以无限复用,只需在配置中修改枚举即可适配不同功能。
- 易于维护:新增功能模块只需添加枚举,无需修改现有架构代码。
这种基于 MV 模式的架构设计,能够有效支撑中大型项目的 UI 开发需求。