元某人也元某人也

Unity 客户端基础小框架

本文目录

这篇文章讲的是工程决策,不是 API 用法。凡是「为什么这么选」的地方都写了代价,凡是「效果如何」的地方都标了怎么测。

一、一页速览

项内容
项目定位教学向 Unity 客户端基础框架,新工程可以直接拿去做骨架
我的角色独立完成:问题拆解、模块边界划分、编码实现、文档编写
核心模块单例基类、缓存池、事件中心、Mono 桥接、资源加载
技术栈Unity、C#、泛型与反射、设计模式
验证方式Demo 场景手测 + Unity Profiler 的 GC Alloc 对比 + 边界用例自测
当前状态持续维护,每补一个模块同步一篇笔记

二、背景:为什么要自己写一套

做小 Demo 和练手工程时,同样的问题每次都要重新解一遍:

  • 全局访问点:Manager 类越写越多,Awake 里互相 GetComponent,初始化顺序全靠猜;
  • 频繁创建销毁:子弹、飘字、列表项反复 Instantiate / Destroy,Profiler 里 GC Alloc 一路涨,低端机上出现可感知的卡顿;
  • 模块耦合:UI 直接调战斗逻辑,改一个需求要顺着调用链改五处;
  • MonoBehaviour 依赖:工具类、数据类想要 Update 或协程,只能被迫继承 MonoBehaviour,凭空多出一堆空挂载脚本。

这四件事单独看都不难,难的是每次新工程都要重来一遍,且每次做法都不一样。所以目标很明确:把这部分固定成骨架,让后续项目只需要关心业务。

三、我的职责

  • 拆边界:先确定哪些是「所有工程都要用」的通用能力,哪些必须留给业务层,避免框架一口吃成引擎;
  • 定接口:每个模块只暴露最小方法集(如对象池只给 Get / Release / Clear),把生命周期钩子收敛到基类;
  • 实现与文档:五个模块全部手写,同时输出可复制的代码片段与使用说明,保证「换个工程能直接落地」;
  • 验证:为每个模块准备最小 Demo 与边界用例,重点测重复注册、忘记归还、异常销毁这类常见误用。

四、技术选择与理由

面临的问题我的选择为什么代价 / 取舍
全局唯一访问点泛型单例基类 + 统一生命周期钩子子类不必重复写 Awake 与 DontDestroyOnLoad,初始化时机统一静态引用不利于单测,需要保留手动清理入口
频繁创建销毁按 Prefab 分桶的对象池复用实例,削掉运行时的 GC 峰值归还时必须重置状态,漏了会出「幽灵数据」
模块间通信事件中心(以类型为 key 的注册表)UI 与逻辑解耦,新增监听方不需要改发送方调用链变隐式,需要额外的调试输出才能追踪
非 Mono 类要 Update / 协程Mono 桥接:单例驱动 Update 队列 + 协程宿主工具类、数据类不用继承 MonoBehaviour执行顺序由桥接统一调度,必须显式约定优先级
资源加载统一的加载封装(同步 + 异步)调用方不直接碰 Resources,方便日后替换实现当前实现基于 Resources,不适用于热更新场景

一个具体的取舍例子:事件中心最初打算用 string 作事件名,好处是调试时能直接打印名字;最后改成以类型为 key,因为字符串拼错编译器不会报错——这类错误往往上线才暴露。代价是需要在事件中心里维护一张映射表,用来输出可读的事件名。

五、结构

分层上刻意保持扁平:单例与桥接在底层提供运行环境,缓存池与事件中心是中层的通用设施,资源加载负责与外部资源打交道。业务代码只允许依赖中层的接口,不允许反过来让框架知道业务。

六、验证结果

验证不是「跑起来没报错」,而是每条主张都有对应测法:

主张怎么测结果
对象池能消掉运行时 GC 峰值同一 Prefab 连续生成/销毁 1000 次,对比开启与关闭对象池时 Profiler 的 GC Alloc待补:采集截图与数值
单例不会重复实例化场景内故意挂两个同类 Manager,检查是否有告警且只保留一个待补:补充日志截图
事件中心不会泄漏注册后销毁对象,检查注册表长度是否回落待补:补充数据
非 Mono 类能拿到逐帧更新用一个纯 C# 计时器类驱动 UI 倒计时,与 MonoBehaviour.Update 结果对比待补:补充对比结论

这一节的数值目前是空的。没有实测数据就不写结论——填上实测截图与数字之后再改这段说明。

七、复盘

  • 对象池的归还重置最容易漏:早期只重置位置和速度,结果复用的对象带着上一次的血条和动画状态,排查花的时间比写池子还长。后来把重置收敛成一个虚方法,由使用方强制实现。
  • 事件中心缺少注销约定:一开始靠使用方自觉,实际几乎没人记得,于是把注销挂到对象的销毁流程里。
  • 框架的边界比功能更重要:最初想把音频、存档也塞进来,后来发现这些在不同项目里差异太大,塞进框架反而变成负担,最终只保留其中最通用的五个模块。

八、相关文章

这个框架的每个模块都对应一篇笔记,按顺序读能看清演进过程:

也可以从 Unity 基础与工具系列 顺着读下去。

仅用于交流学习,记录学习心得