Unity 游戏开发框架设计笔记
一款自己从零搭建的 Unity 开发框架,沉淀了多年项目中的通用能力,覆盖 UI、资源、场景、输入、定时器、红点 等模块,服务端(C#)与 Unity 客户端共用,目标是用一套代码解决团队高频复用的基础问题。
一、基础框架功能(2021.9)
框架的第一版,先把游戏开发里”绕不开的基础设施”搭好。设计原则是每个模块职责单一、可插拔、不相互依赖,方便项目按需取用。
UI 模块
- 统一的 界面管理(打开/关闭/层级管理);
- 支持 UI 预加载与缓存,避免频繁实例化;
- 提供界面之间的事件通信,降低耦合。
缓存池模块
- 对象池化:游戏物、特效、子弹等高频创建销毁对象统一池化;
- 减少
Instantiate / Destroy带来的 GC 与卡顿; - 支持 自动回收 与 按需扩容。
资源加载模块
- 统一的资源加载入口(同步/异步);
- 支持 引用计数 与 自动卸载,避免资源泄漏;
- 为 Addressable / AssetBundle 预留扩展接口。
场景加载模块
- 统一场景切换入口(含异步加载、进度回调);
- 管理加载中的加载界面与状态回调;
- 支持场景叠加与切换的扩展。
音乐管理模块
- BGM / 音效的统一播放与管理;
- 音量控制、暂停/恢复、音效池;
- 全局单例,任何模块可调用。
管理基类模块(继承/不继承 Mono)
这是框架最有辨识度的一点——管理类分成两种:
| 类型 | 特点 | 适用 |
|---|---|---|
| 继承 Mono | 依赖 MonoBehaviour,走 Update 生命周期 | 需要每帧逻辑、挂载到场景对象的模块 |
| 不继承 Mono | 纯 C# 类,不依赖引擎生命周期 | 服务端逻辑、可脱离引擎运行、易单测 |
意义:同一套业务逻辑,既能跑在 Unity(继承 Mono),也能跑在纯 C# 环境(不继承),为双端复用打基础。
UI 事件管理器
- 全局事件发布/订阅;
- 解耦 UI 与业务(UI 订阅事件,业务发事件,互不引用);
- 支持带参数与带优先级的事件。
输入管理模块
- 统一封装键盘、鼠标、触摸输入;
- 屏蔽平台差异(PC / 移动端);
- 提供输入事件回调,业务不直接监听底层输入。
二、定时器功能模块(2024.5)
定时器是游戏逻辑的”心脏”——技能冷却、Buff 跳结算、野怪刷新、倒计时都离不开它。本项目定时器模块解决了”既要在 Unity 用、又要在服务器用“的痛点。
继承 Mono / 不继承 Mono 双实现
和框架基调一致,定时器也提供两种形态:
- 继承 Mono 版:在 Unity 内用,依赖 Update / 协程驱动,方便直接挂载;
- 不继承 Mono 版:纯 C# 实现,服务器可用,用主循环/Tick 驱动,不依赖引擎。
▎真实代码(两种实现核心逻辑一致,仅”驱动源”不同)
继承 Mono 版(Assets/Scripts/Manager/Timer/AtimerMono.cs)由 Update() 驱动,用 Time.deltaTime 推进:
1 | public class AtimerMono : BaseMonoManager<AtimerMono> |
不继承 Mono 版(Assets/Scripts/Manager/Timer/ATimer.cs)用 System.Timers.Timer(1ms) 驱动,可在服务器/纯 C# 环境运行:
1 | public class ATimerMgr : BaseManager<ATimerMgr> |
同一套 TimerInfo 结构与 Delay/DelayLoop/DelayFrame/NextFrame API,只换驱动源——这正是”服务器和 Unity 都支持、毫秒级、支持每帧”的来源。
服务器与 Unity 都支持
一套定时器 API,双端通用:
1 | // 延迟执行 |
服务器端用它做战斗周期任务,Unity 端用它做 UI 倒计时、技能冷却,同一套心智模型。
毫秒级精度
时间基准统一为毫秒,配合 DateTime/Stopwatch 计时,避免浮点误差导致的定时漂移,适合对精度敏感的战斗/服务端逻辑。
支持每帧(每 Tick)回调
除了”延时/间隔”两种模式,还支持每帧/每 Tick 执行:
- Unity 端:作为轻量级 Update 分发器,替代部分 MonoBehaviour Update;
- 服务器端:作为主循环的 Tick 分发,统一驱动多个模块的帧逻辑。
好处:模块只需注册回调,无需各自维护 Update/循环,代码更干净、也便于统一测试。
三、红点系统(2024.6)
红点(提示角标)是游戏 UI 的标配,但维护起来很痛——层级多、来源杂、数量要实时。本项目红点系统解决了多层级与动态数量两大痛点。
支持多层级
红点不是”一个开关”,而是树状结构:
1 | 主城 → 邮箱(未读) → 邮件系统 |
- 每个节点可挂红点状态;
- 父节点自动聚合子节点的红点(子节点有红点,父节点也亮);
- 刷新沿树向上传播,一次数据变更自动更新所有相关节点。
▎真实代码(Assets/Scripts/Manager/RedDot/ 精简)
节点树 + 向上传播(RedDotNode.cs):子节点状态变了,UpdateState 会递归刷新父节点:
1 | // 更新红点状态:子节点有红点则父节点也亮,数量向上聚合 |
无限嵌套 + GameObject 绑定(RedDotSystem.cs):支持任意层级挂节点,绑定 GameObject 后自动显隐、显示数字:
1 | // 添加子节点(无限嵌套):parent 下挂 children |
红点类型(RedDotType)区分 Normal(纯红点)/ Number(数量角标)/ Exclamation(叹号),对应不同显示回调——这就是”多层级、绑定 GameObj、数量显示、多类型显示”的实现。
绑定 GameObj
红点节点可绑定到具体 GameObject(图标、按钮),自动挂载角标并随对象生命周期管理,无需手写 Show/Hide。
支持数量显示
除了”亮/灭”,还支持数字角标(如”未读邮件 12 封”):
- 节点维护一个计数;
- 达到阈值显示数字,超阈值显示
99+; - 计数变化自动刷新角标文案。
支持多类型显示
同一节点可按需呈现不同形态:
- 纯红点:仅一个圆点;
- 数字角标:显示数量;
- 自定义图标 / 动效:可扩展。
实现要点
- 数据驱动:红点状态由业务数据(计数)计算,而非手动开关;
- 增量刷新:只有数据变化的节点及其祖先被刷新,避免全量遍历;
- Todo 记录:如”未打开子节点时红点显示是否正常”这类边界,用清单跟踪。
小结
这套框架覆盖了游戏开发的高频基础设施,核心特色是**”继承 / 不继承 Mono 双实现”**,让同一套 C# 逻辑既能在 Unity 表现、也能在服务器运行,为双端项目省去大量重复代码。
后续方向:编辑器工具链(一键打包、热更新)、网络模块接入、红点系统的可视化调试。
更多作品见:本人作品