我为什么开源一个用了 5 年的 Unity 游戏框架
最近我把自己长期使用的一套 Unity 游戏框架整理成了一个可以直接运行的 Demo,并放到了 GitHub 上。
项目地址:
https://github.com/ZHOURUIH/MyFramework
配套服务器框架:
https://github.com/ZHOURUIH/MyServerFramework
这个框架叫 MyFramework。
它不是我最近为了开源临时写的一个 Demo,也不是一个只停留在学习阶段的练手框架,而是我自己在实际项目中长期使用、不断修改、不断验证之后沉淀下来的一套 Unity 游戏开发框架。
目前这套框架已经持续迭代多年,也已经用于我自己的 MMORPG / 传奇类项目,以及公司的手游项目中。
这篇文章主要想聊一下:
-
我为什么要写自己的 Unity 框架
-
这个框架主要解决什么问题
-
它和常见 Unity 框架的区别在哪里
-
为什么我最终决定把 Demo 开源出来
-
后续希望它往什么方向发展
一、为什么要自己写框架
很多 Unity 项目刚开始的时候,其实并不需要复杂框架。
新建一个场景,拖几个 Prefab,写几个 MonoBehaviour,绑定几个按钮,就可以很快看到效果。
但是项目一旦变大,问题就会慢慢出现。
比如:
-
UI 越来越多,查找节点和绑定事件越来越混乱
-
配置表越来越多,引用错误很难提前发现
-
网络消息越来越多,客户端和服务器协议容易不一致
-
资源越来越多,很难知道谁在加载、谁在持有、谁该释放
-
场景流程越来越复杂,状态切换变得难以维护
-
各种临时写法越来越多,后期定位问题非常痛苦
如果只是做一个小 Demo,这些问题可能不明显。
但如果是一个长期维护的商业项目,尤其是 RPG、MMO、SLG、模拟经营这类系统比较多的项目,这些问题会不断放大。
我最开始写这套框架的目的其实很简单:
让项目里大部分逻辑都有明确的位置,明确的生命周期,明确的调用关系。
我不希望项目最后变成:
-
一个按钮点击后不知道触发了哪些逻辑
-
一个资源不知道是谁加载的
-
一个 UI 不知道什么时候打开、什么时候关闭
-
一个网络消息不知道客户端和服务器是否一致
-
一个配置表 ID 写错了只能运行时才发现
所以 MyFramework 从一开始就不是为了“封装 Unity API”,而是为了让项目更可控。
二、框架的核心思想:可控、可维护、低 GC
MyFramework 的整体代码风格会比较偏传统游戏引擎,也比较偏 C++ 风格。
我自己更关注几个点:
1. 生命周期要明确
很多 Unity 默认机制虽然方便,但是也会带来隐藏逻辑。
比如 MonoBehaviour 的 Awake、Start、OnEnable、Update、OnDestroy 等回调在小项目中很方便,但在大型项目里,如果大量业务逻辑分散在各种 MonoBehaviour 中,后期会很难追踪。
所以 MyFramework 中大部分系统并不依赖 MonoBehaviour,而是由框架统一调度:
-
init
-
update
-
lateUpdate
-
fixedUpdate
-
destroy
这样每个系统什么时候初始化、什么时候更新、什么时候销毁,都更加明确。
2. 资源生命周期要明确
Unity 项目里资源问题很常见。
资源到底是从 AssetDatabase 加载,还是从 AssetBundle 加载?
资源加载后由谁持有?
什么时候释放?
异步加载过程中对象被销毁怎么办?
这些问题如果没有统一管理,项目越大越容易出问题。
所以框架里封装了资源管理系统,业务层不需要关心资源到底来自编辑器还是 AssetBundle,只需要通过统一接口访问资源。
同时,加载资源时也要求考虑资源生命周期,避免产生无人管理的资源引用。
3. 尽量减少 GC
Unity 项目中 GC 问题很常见,尤其是移动端项目。
MyFramework 中做了很多对象池和 Scope 设计,例如:
-
类对象池
-
List 对象池
-
GameObject 对象池
-
Prefab 对象池
-
Effect 对象池
-
各种临时容器 Scope
这些设计不是为了炫技,而是为了减少频繁分配临时对象导致的 GC。
很多工具函数也尽量避免不必要的堆内存分配。
4. 不追求最少代码,而是追求可维护
有些框架追求写法简洁,一行代码解决很多事情。
但我的选择不太一样。
我更倾向于让逻辑显式一些。
代码可能多一点,但是出问题时能找到。
这也是 MyFramework 的一个明显特点:
不追求最短代码,而追求长期项目中更容易维护的代码。
三、MyFramework 不只是运行时框架,更像一套工具链
如果只看运行时模块,MyFramework 里有常见的:
-
UI 框架
-
资源管理
-
网络框架
-
对象池
-
事件系统
-
命令系统
-
场景流程系统
-
特效系统
-
Tween 系统
-
多语言系统
-
红点系统
-
输入系统
但我认为它真正有价值的地方,不只是这些模块,而是整套开发工具链。
1. UI 代码自动生成
Unity UI 开发中,经常会写大量查找节点的代码。
比如:
-
查找按钮
-
查找文本
-
查找图片
-
查找列表项
-
绑定成员变量
-
注册事件
这些代码本身没有太高技术含量,但是非常容易写错,也很浪费时间。
MyFramework 中提供了 UI 自动生成工具。
大致流程是:
UI Prefab
↓
UGUIGenerator
↓
生成 UI 成员变量
↓
生成节点查找代码
↓
编写业务逻辑
这样做的好处是:
-
减少手写重复代码
-
减少节点名写错的问题
-
UI 结构变化后可以重新生成
-
手写逻辑代码可以保留
-
UI 脚本结构更统一
对于 UI 很多的项目,这个功能非常实用。
2. 配置表工具链
很多游戏项目都离不开配置表。
配置表的问题不在于读取,而在于检查。
比如:
-
字段类型是否正确
-
ID 是否重复
-
引用的 ID 是否存在
-
填写的资源路径是否存在
-
枚举值是否合法
-
列表长度是否匹配
-
客户端和服务器是否使用同一份结构
MyFramework 使用 CSV 作为配置表格式,并配套自研表格编辑器和代码生成工具。
目标是尽量在编辑阶段发现问题,而不是等运行时才报错。
大致流程是:
CSV 配置表
↓
表格编辑器
↓
字段检查 / 引用检查 / 路径检查
↓
生成客户端表格代码
↓
生成服务器表格代码
这对于长期项目非常重要。
因为配置表问题往往不是程序错误,而是数据错误。
如果不能提前检查,后期会非常难排查。
3. 网络协议代码生成
客户端和服务器通信时,消息协议一致性非常重要。
如果客户端字段顺序和服务器字段顺序不一致,或者某一端改了协议另一端没改,就会出现很隐蔽的问题。
MyFramework 的协议工具链可以根据协议配置自动生成客户端和服务器消息代码。
包括:
-
消息类
-
字段定义
-
序列化代码
-
反序列化代码
-
消息注册代码
大致流程是:
协议配置
↓
协议生成工具
↓
生成客户端消息代码
↓
生成服务器消息代码
↓
自动注册消息
同时支持手写逻辑代码保留,避免每次生成都覆盖业务逻辑。
这点在实际项目中非常重要。
4. 客户端和服务器配套
很多 Unity 框架只关注客户端。
但我的项目本身需要服务器,所以 MyFramework 还有配套服务器框架:
https://github.com/ZHOURUIH/MyServerFramework
客户端和服务器可以共享:
-
协议生成
-
表格生成
-
消息结构
-
部分工具链思想
这也是我认为 MyFramework 比较特殊的地方。
它不是单纯的客户端框架,而是更偏向完整游戏项目开发流程。
四、热更新分层
MyFramework 使用 HybridCLR 做热更新。
但在框架结构上,我没有简单地把所有代码都放在一个热更工程里,而是做了比较明确的分层。
主要目录大致是:
Frame_Base 不可热更,最基础的框架代码
Frame_Game 不可热更,项目非热更代码的框架
Game 不可热更,项目应用层启动逻辑
Frame_HotFix 可热更,框架层热更代码
HotFix 可热更,项目应用层热更代码
依赖关系大致是:
Frame_Base -> Frame_HotFix -> HotFix
Frame_Base -> Frame_Game -> Game
Game -> HotFix
这样做的目的是:
-
保留最基础启动逻辑的稳定性
-
尽量让框架层也具备热更新能力
-
让业务层可以完整热更
-
区分不可热更代码和可热更代码
目前除了启动和热更新下载相关逻辑外,大部分框架层和业务层代码都可以参与热更新。
五、为什么不用一些常见方案
MyFramework 中有不少选择可能和很多 Unity 项目不同。
比如:
-
尽量减少 MonoBehaviour
-
尽量减少协程
-
不依赖 DoTween
-
不依赖 ProtoBuf
-
不依赖 Addressables
-
不使用 UGUI EventSystem 作为主要输入系统
-
不大量使用反射
-
不大量依赖第三方插件
这些不是因为这些方案不好,而是因为我的目标不同。
我更关注:
-
执行时机是否明确
-
生命周期是否可控
-
出问题是否容易定位
-
是否适合长期维护
-
是否能减少隐藏逻辑
例如 DoTween 很好用,但我希望 Tween 行为完全由框架控制。
ProtoBuf 很成熟,但我希望协议结构和序列化逻辑完全按项目需求生成。
Addressables 功能完整,但我希望资源系统同时支持同步和异步,并且业务层不感知 AssetDatabase 和 AssetBundle 的差异。
所以这些选择不是“谁更好”的问题,而是项目目标不同。
MyFramework 更偏向强控制、强规范、低 GC、长期维护。
六、工程检查工具
大型项目中,很多问题并不是运行时逻辑错误,而是工程规范问题。
比如:
-
文件命名不规范
-
资源路径错误
-
图集引用错误
-
材质引用丢失
-
热更代码引用了不该引用的内容
-
UI 适配组件遗漏
-
多语言文本配置错误
-
代码行太长
-
命名不符合规范
-
注释或空行不符合规范
这些问题如果靠人工检查,很难保证稳定。
所以 MyFramework 的 Editor 中提供了大量检查工具。
包括:
-
代码规范检查
-
空行检查
-
空格检查
-
单行长度检查
-
命名规范检查
-
函数排版检查
-
注释检查
-
命令命名规范检查
-
热更引用检查
-
资源引用查找
-
未引用资源检查
-
材质引用丢失检查
-
图集引用检查
-
多语言文本检查
-
UI 适配组件检查
-
资源文件名规范检查
-
预设根节点变换检查
-
热更与非热更资源互相引用检查
这些工具对商业项目很重要。
因为项目越大,越不能只依赖个人经验和人工检查。
七、单元测试
MyFramework 中也包含大量单元测试。
主要覆盖:
-
序列化
-
字符串工具
-
数学工具
-
文件工具
-
容器扩展
-
Scope
-
命令系统
-
事件系统
-
场景流程
-
UI 基础逻辑
-
网络消息
我个人非常重视工具函数的正确性。
因为工具函数一旦有问题,影响范围会非常大。
所以对于可测试的代码,我会尽量补充单元测试,保证基础逻辑长期稳定。
八、这个框架适合什么人
MyFramework 不一定适合所有 Unity 开发者。
它比较适合:
-
想研究 Unity 商业项目架构的人
-
想做长期项目的人
-
想做 RPG / MMO / SLG / 模拟经营项目的人
-
想研究热更新分层的人
-
想研究客户端和服务器配套工具链的人
-
想研究 UI 自动生成、协议生成、配置表生成的人
-
喜欢强规范、强控制代码风格的人
它不一定适合:
-
只想快速做一个小 Demo 的人
-
完全不想看框架源码的人
-
更喜欢 Unity 原生工作流的人
-
更喜欢高度自动化、黑盒式框架的人
MyFramework 的学习成本不算最低。
因为它有比较强的代码风格和架构约束。
但是如果你认同这种强控制、强规范、长期维护的思路,它会很适合研究。
九、为什么现在开源
我自己一直在用这套框架做项目。
但一个人长期维护框架,很容易陷入自己的思维惯性。
很多设计在我看来很自然,但对别人来说可能不够直观。
很多接口我自己用得很顺手,但别人第一次用可能会觉得难理解。
所以我希望通过开源 Demo 的方式,让更多人看到这套框架,也希望得到更多反馈。
包括:
-
哪些地方不好理解
-
哪些文档需要补充
-
哪些工具更有价值
-
哪些设计不够合理
-
哪些模块可以进一步独立出来
目前仓库已经可以直接运行 Demo,不需要服务器也可以启动。
GitHub 地址:
https://github.com/ZHOURUIH/MyFramework
QQ群:
805116283(MyFramework 官方交流群)
欢迎感兴趣的开发者一起交流。
十、后续计划
后续我会继续整理和上传更多配套内容。
包括:
-
表格编辑器源码
-
代码生成工具源码
-
更多 Demo 示例
-
更多文档
-
Google 登录
-
Google 支付
-
AAB PAD 打包流程
-
服务器框架更多说明
我希望 MyFramework 不只是一个自己项目里用的框架,而是能逐步变成一套可供更多人参考、使用和反馈的 Unity 游戏开发工具链。
结语
MyFramework 不是一个追求最新概念的框架。
它更像是一个长期项目中不断沉淀出来的工程体系。
它的目标不是让代码看起来最短,而是让项目长期运行、长期维护、长期迭代时更稳定、更可控。
如果你正在做 Unity 商业项目,或者正在研究游戏框架设计、热更新、UI 自动生成、配置表工具链、网络协议生成,也许这个项目能给你一些参考。
项目地址:
https://github.com/ZHOURUIH/MyFramework
服务器框架:
https://github.com/ZHOURUIH/MyServerFramework
如果觉得项目有帮助,欢迎点一个 Star,也欢迎加入交流群一起讨论。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)