10 KiB
FlowScope 框架评审文档
评审日期:2026-05-19
评审对象:My project/Assets/FlowScope
评审范围:Runtime、Tests、Samples、asmdef、核心服务实现与测试覆盖
评审结论:建议有条件通过,定位为 P0/P1 阶段轻量 Unity 游戏基础框架
1. 总体结论
FlowScope 当前已经具备一个轻量游戏框架的基本形态,适合用于小型项目、原型项目或作为后续框架演进的 P0 基座。它的优势在于分层清晰、抽象克制、测试意识较好,并且围绕 Unity 常见横切能力建立了可替换接口。
当前不建议直接定义为稳定生产框架。主要原因是资源异步、运行时对象销毁、Addressables 依赖方式和自研 JSON 转换器仍存在生产风险。这些问题不影响它作为框架雏形继续推进,但应作为进入生产复用前的前置整改项。
2. 技术基线
- Unity 版本:
2022.3.62f2c1 - 主要依赖:
com.cysharp.r3org.nuget.r3com.unity.uguicom.unity.textmeshprocom.unity.timeline
- 目录结构:
Runtime:框架运行时代码Tests/EditMode:编辑器测试Tests/PlayMode:运行时测试Samples/MainMenuP0:P0 示例场景与示例业务
- asmdef:
FlowScope.RuntimeFlowScope.Tests.EditModeFlowScope.Tests.PlayModeFlowScope.Samples.MainMenuP0
3. 现有模块评价
3.1 Flow
代表文件:Runtime/Flow/GameFlow.cs
GameFlow 负责 Feature 生命周期编排,包括启动、切换、关闭、失败清理和状态保护。整体职责清晰,和 IFeature、FeatureContext 的边界较自然。
优点:
- 状态机明确,避免非法状态调用。
- Feature 使用独立 scope,便于做生命周期隔离。
- 失败路径中有资源、容器、Feature 的清理逻辑。
- 测试覆盖了启动、切换、关闭、失败和取消场景。
风险:
StartupAsync固定依赖IConfigProvider.LoadAllAsync,会让无配置项目、分包配置、热更新配置的启动流程不够灵活。GameFlow当前更像“启动编排器 + Feature 生命周期管理器”的混合体,后续业务复杂时可能需要把配置加载职责移回 Bootstrap。
评价:结构良好,建议保留为框架核心,但需要降低对配置加载的硬绑定。
3.2 Container
代表文件:Runtime/Container/Container.cs
自研容器实现轻量,支持实例注册、工厂注册、作用域、父子容器、循环依赖检测和拥有对象释放。
优点:
- API 简单,学习成本低。
- scope 模型适合 Feature 生命周期。
- dispose 顺序和循环依赖都有测试。
- 没有引入大型 DI 框架,符合轻量框架定位。
风险:
GeneratedFactories需要外部注册,长期需要配套生成器或明确手写规范。- 反射工厂适合开发期,但移动端/AOT 环境需要持续验证。
- 当前没有生命周期枚举,例如 transient、scoped、singleton,实际行为需要文档明确。
评价:P0 阶段可接受。后续重点不是扩大能力,而是写清注册规范和 AOT 策略。
3.3 Resources
代表文件:Runtime/Resources/AddressablesResourceService.cs
资源层抽象了 IResourceService、IResourceHandle<T> 和 IResourceGroup,并实现了 Addressables 加载、引用计数和分组释放。
优点:
- 使用句柄释放资源,方向正确。
- 支持同 key 同类型加载去重。
ResourceGroup适合跟随 Feature 生命周期批量释放。- PlayMode 测试覆盖了复用、引用计数和取消等路径。
风险:
- Addressables 通过字符串反射调用,编译期无法发现 API 变化。
- Runtime asmdef 没有显式引用 Addressables,当前设计牺牲了类型安全。
- 取消等待后底层 Addressables 任务可能仍继续执行,后续需要确认资源完成后的释放策略。
评价:抽象方向正确,但 Addressables 适配层应从 Runtime 核心拆出,改为显式依赖的独立 asmdef。
3.4 UI
代表文件:Runtime/UI/UIManager.cs
UI 模块基于 UIPanelAttribute 标记层级和路径,通过 UIManager 加载 prefab、挂载到 Canvas、绑定 ViewModel,并支持 Destroy/Cache 策略。
优点:
- 使用 Attribute 降低打开面板时的字符串散落。
- 支持按层关闭、关闭全部、缓存复用。
- 打开失败时有句柄释放和实例销毁逻辑。
- PlayMode 测试覆盖了路径、层级、缓存、关闭顺序和 Bind 失败。
风险:
- 运行时代码使用
DestroyImmediate,不适合常规 PlayMode/Runtime 生命周期。 - 面板路径约定较隐式,需要文档约束或配置化。
- 当前只允许关闭栈顶面板,适合简单 UI,但复杂弹窗管理可能需要更细的策略。
评价:可作为 P0 UI 管理器,但 DestroyImmediate 应优先修正。
3.5 Audio
代表文件:Runtime/Audio/AudioService.cs
音频模块提供 BGM、SFX、音量、静音、淡入淡出和 SFX 池。
优点:
- 接口简单,适合快速接入。
- SFX 池和复用策略清楚。
- PlayMode 测试覆盖了播放、停止、池耗尽、音量和淡入淡出。
风险:
LoadClip内部使用.GetAwaiter().GetResult()同步等待异步资源加载,在 Unity 主线程和 Addressables 场景下存在卡顿或死锁风险。- 音频服务是
MonoBehaviour,但依赖通过Initialize注入,需要文档明确创建流程。 - 当前播放接口是同步方法,与异步资源系统存在模型冲突。
评价:功能够用,但异步资源加载方式必须调整后才适合生产复用。
3.6 Save / Config / Data
代表文件:
Runtime/Save/SaveService.csRuntime/Config/JsonConfigProvider.csRuntime/Data/ReactivePropertyJsonConverter.cs
数据相关模块围绕 R3 的 ReactiveProperty 做了 JSON 序列化、存档读写和配置加载。
优点:
- Save 的 storage 和 serializer 可替换。
- Config 支持多表加载和重复 id 检查。
- Data 层能处理
ReactiveProperty<T>,契合 R3 数据模型。 - 相关 EditMode 测试较完整。
风险:
- JSON parser/serializer 是自研实现,长期边界成本较高。
- 当前更适合简单 DTO,不适合复杂对象图、版本迁移、字段重命名、特殊字符完整兼容等场景。
GetAll<T>返回新 List,顺序来自 Dictionary values,不应作为稳定排序依赖。
评价:P0 可以使用,但应明确“简单数据模型”边界。生产化建议接入成熟 JSON 库,保留 R3 适配层。
4. 测试覆盖评价
现有测试覆盖优于一般框架雏形,尤其是:
GameFlowTests覆盖生命周期和异常清理。ContainerTests覆盖注册、scope、dispose、循环依赖。UIManagerTests覆盖 UI 打开、关闭、缓存和异常。AudioServiceTests覆盖播放、停止、池和音量。SaveServiceTests、JsonConfigProviderTests、DataSerializationTests覆盖数据链路。
仍建议补充:
- Addressables 真实包接入测试或集成验证。
- AOT/linker 场景验证。
- UI 使用
Destroy后的帧级测试调整。 - 音频异步加载接口改造后的取消、失败和重复播放测试。
- Config/Save 数据版本迁移测试。
5. 主要风险清单
| 优先级 | 风险 | 影响 | 建议 |
|---|---|---|---|
| P0 | AudioService 同步等待异步资源 |
可能导致主线程卡顿或死锁 | 改为异步播放或预加载机制 |
| P0 | Runtime 使用 DestroyImmediate |
运行时生命周期不稳 | 改为 Destroy,测试按帧等待 |
| P1 | Addressables 反射调用 | 类型安全弱,升级风险高 | 拆独立 Addressables 适配 asmdef |
| P1 | 自研 JSON 转换器 | 边界和维护成本高 | 明确 DTO 限制或接入成熟 JSON 库 |
| P1 | GameFlow 固定加载配置 |
启动流程不够弹性 | 配置加载移到 Bootstrap 或可选策略 |
| P2 | 容器生命周期语义文档不足 | 使用者容易误判对象生命周期 | 补充注册和释放规范 |
6. 审批意见
结论:有条件通过。
通过范围:
- 可继续作为 FlowScope P0/P1 基础框架推进。
- 可用于示例项目、小型原型项目和内部验证项目。
- 可作为后续 Runtime 包化、模块拆分和 API 稳定化的基础。
限制条件:
- 暂不建议标记为生产稳定版本。
- 暂不建议在多人长期项目中无约束扩散使用。
- 在进入生产复用前,必须完成 P0 风险整改。
前置整改项:
- 将
UIManager运行时销毁逻辑从DestroyImmediate调整为Destroy。 - 将
AudioService的资源加载从同步阻塞改为异步或预加载模型。 - 为 Addressables 适配明确依赖策略,优先拆出独立 asmdef。
- 补充框架使用约定文档,包括 Bootstrap、Feature、资源释放、UI 路径、配置 DTO 限制。
7. 后续建议
短期建议:
- 先修生命周期和异步资源问题,不急于扩展新模块。
- 保持框架轻量,不引入事件总线、复杂状态机编辑器、大型 DI 等重能力。
- 将 Samples 继续作为验收样板,所有框架规则都应能在 Sample 中体现。
中期建议:
- 将 Runtime 拆为核心层和适配层,例如
FlowScope.Runtime、FlowScope.Addressables。 - 为容器工厂生成建立明确流程,降低手写注册成本。
- 给 Save/Config 增加数据版本和迁移策略。
长期建议:
- 明确 FlowScope 的定位:小型游戏基础设施,而不是全能游戏引擎框架。
- API 稳定后再考虑 package 化和跨项目复用。
- 保持测试先行,所有生命周期规则和失败路径都应有测试保护。
8. 最终评级
| 维度 | 评级 | 说明 |
|---|---|---|
| 架构清晰度 | 良好 | 模块边界清楚,抽象克制 |
| 可测试性 | 良好 | 已有较完整 EditMode/PlayMode 测试 |
| Unity 生命周期安全 | 一般 | DestroyImmediate 和同步等待需修正 |
| 生产稳定性 | 一般 | 仍处于 P0/P1 框架雏形 |
| 可演进性 | 良好 | 适合继续拆模块、补规范、稳定 API |
综合评级:B+。
结论摘要:FlowScope 是一个有工程意识的轻量 Unity 框架骨架,值得继续推进;但在正式生产复用前,需要优先修正异步资源、运行时销毁和 Addressables 依赖方式三个关键问题。