外观
VContainer Installer扩展(DI)
约 1744 字大约 6 分钟
2026-03-14
重要
请先确保你对Dependency Injection(DI)和 VContainer的基本工作原理有一定认知;如果没有,请先硅基生物,以及搭配VContainer文档食用
本文默认你已经了解以下基础概念:
- DI 的目的(解耦、可替换、可测试)
- VContainer 的基础用法(
LifetimeScope、IContainerBuilder、Lifetime)
本文重点不是重复 DI 教程,而是回答三个问题:
- 这个项目在 VContainer 之上额外封装了什么。
- 这些封装分别解决了什么协作问题。
- 在 Cofcity 里如何实际使用与排错。
2. 封装总览:在原生 VContainer 之上加了哪些层
Ruka/Cofcity 的扩展核心在于把“安装逻辑”拆成可组合、可过滤、可自动收集的模块。
2.1 类型关系(简化)
InstallerBase (ScriptableObject)
├─ CompositeInstaller // 资产级聚合器
├─ AutoGroupCollectionInstaller // 自动分组收集执行器
└─ 各业务 InstallerAsset(如 StateMachineInstaller 等)
IInstallerFilter
├─ IProjectInstaller
└─ ISceneInstaller
NestedLifetimeScope
└─ CompositeLifetimeScope // 场景/预制体上的 Scope 聚合器2.2 各模块的职责
LifetimeScope扩展
CompositeLifetimeScope:把组合安装能力直接挂到场景/Prefab 上(继承NestedLifetimeScope)。NestedLifetimeScope:自动找父 Scope,降低手工拖拽 parent 的维护成本。
资产型Installer
InstallerBase:统一安装器资产基类,所有安装入口统一成Install(IContainerBuilder builder)。CompositeInstaller:把多个InstallerBase资产组合起来,并可按过滤接口筛选。
自动维护型Installer
FeatureInstallerAttribute + IFeatureInstaller:支持“纯 C# 安装器类”声明分组和顺序。AutoGroupCollectionInstaller:把某个 Group 对应的IFeatureInstaller自动执行,不再手动维护长列表。(这个是要创建资产的Installer,相当于一个资产管一组FeatureInstaller)InstallerManifestProcessor(Editor):脚本重载或资产导入时,自动刷新分组清单。
3. 运行链路:项目里一次容器装配是怎么发生的
以 Cofcity 的项目级和关卡级为例:
- 场景中的 Scope 节点(如
ProjectContext、StageRootScope)挂CompositeLifetimeScope。 CompositeLifetimeScope根据moduleInstallers执行安装器资产。- 其中某些是
CompositeInstaller资产(例如ProjectContextInstallers.asset、StageSceneInstallers.asset),继续展开子安装器。 - 子安装器里可包含
AutoGroupCollectionInstaller资产(如ProjectCoreGroupInstaller.asset、StageFeaturesGroupInstaller.asset)。 AutoGroupCollectionInstaller执行qualifiedTypes中的IFeatureInstaller类型;这个列表由 Editor 自动回填并按Order排序。- 最终所有注册汇总进当前 Scope 的 VContainer 容器。
4. 关键模块解读与使用方式
4.1 InstallerBase:统一安装入口
public abstract class InstallerBase : ScriptableObject, IInstaller
{
public abstract void Install(IContainerBuilder builder);
}使用建议:
- 需要暴露为可配置资产(可拖拽、可复用)时,用
InstallerBase子类。 - 纯代码特性驱动、无需资产实例化时,用
IFeatureInstaller。
4.2 CompositeInstaller:资产列表聚合
适合把多个安装器资产打包成一个“安装包”。
特点:
moduleInstallers:组合列表。filter:可选过滤器类型(常见为IProjectInstaller/ISceneInstaller)。
典型用途:
ProjectContextInstallers.asset里集中挂项目级模块。StageSceneInstallers.asset里集中挂关卡相关模块。
4.3 NestedLifetimeScope / CompositeLifetimeScope:Scope 侧的工程化封装
NestedLifetimeScope 解决两个常见问题:
- 父子 Scope 链接:
autoParent自动向上查找父LifetimeScope。 - 构建时序:如果父容器还没准备好,会等待后再构建,减少初始化竞态。
CompositeLifetimeScope 在此基础上增加了“可配置安装器列表”,用于场景节点直接编排模块。
常用字段理解:
autoParent:推荐开启(窗口/子节点场景最常见)。parentScope:仅在关闭autoParent时才生效。autoInjectSelf:需要自注入当前物体时开启。filter:限制可执行安装器类型。
4.4 FeatureInstaller + AutoGroupCollectionInstaller:自动分组收集
重要
底下这个会用的比较多
4.4.1 代码侧声明
[FeatureInstaller(InstallerGroupNames.ProjectCore, 100)]
public sealed class StaticDataProjectFinstaller : IFeatureInstaller
{
public void Install(IContainerBuilder builder)
{
// 注册逻辑
}
}规则:
- 必须实现
IFeatureInstaller。 - 必须是可实例化类(不能抽象)。
Group不能为空。Order越小越先执行。
4.4.2 资产侧执行
AutoGroupCollectionInstaller 通过 targetGroup 指定组,例如:
ProjectCoreProjectFeaturesStageCoreStageFeaturesMock
Editor 会自动扫描带 [FeatureInstaller] 的类型并回填 qualifiedTypes,运行时依次执行。
这意味着:
- 日常新增模块通常只改代码即可,不必手动维护长列表。
- 若编辑器自动刷新未触发,可手动重新导入相关资产或触发脚本重载。
4.5 InstallerGroup 与 Symbol 体系
InstallerGroup 本质是 Symbol<T> 的一个类型化 ID。
在 Cofcity 中,分组常量集中在 InstallerGroupNames / CofcityInstallerGroups,便于:
- Inspector 下拉选择(
SymbolSelector)。 - 代码常量统一,避免硬编码字符串漂移。
4.6 StateMachineInstaller:业务安装器样例(含 SymbolSelector)
StateMachineInstaller 是 InstallerBase 子类,同时标记了 IProjectInstaller 和 ISceneInstaller。
关注点:
stateMachineId字段用Symbol<FsmId>,Inspector 通过SymbolSelector选值。- 默认值是
DefaultFSM,但项目建议使用业务常量(例如 Gameflow/Deploy 的FsmId)。 - 安装时通过
Keyed(stateMachineId.ToString())把状态机、状态、守卫归到同一命名空间键。
对 TA 的含义:
- 若状态机资产引用错了
FsmId,可能导致状态机查找/触发不匹配。 - 资源配置阶段应优先选择已有 Symbol 常量,而不是临时手输。
5. 在 Cofcity 中的推荐接入流程
5.1 新增一个功能模块(推荐流程)
- 在对应程序集新增一个
IFeatureInstaller类。 - 用
[FeatureInstaller(InstallerGroupNames.XXX, order)]声明目标组和顺序。 - 在
Install内完成注册。 - 等待编辑器自动刷新
AutoGroupCollectionInstaller的qualifiedTypes。 - 运行场景验证该组所在 Scope 是否生效。
5.2 新增一个组(仅在确有分层需求时)
- 在
InstallerGroupNames增加组名常量。 - 在
CofcityInstallerGroups暴露对应Symbol<InstallerGroup>。 - 新建
AutoGroupCollectionInstaller资产,targetGroup指向新组。 - 将该资产挂入对应的
CompositeInstaller(项目级或场景级)。
5.3 让某个 Scope 只吃某类安装器
- 在
CompositeLifetimeScope或CompositeInstaller上设置filter:- 项目上下文常用
IProjectInstaller - 场景上下文常用
ISceneInstaller
- 项目上下文常用
说明:
StageSceneInstallers.asset当前配置可留空过滤器,表示不额外限制;这是允许的,但要保证列表维护清晰。
6. 策划/TA 常见工作边界
适合策划/TA直接处理:
- 调整资产中的安装器组合顺序(在明确依赖关系时)。
- 选择正确的
targetGroup。 - 校验场景 Scope 是否引用了正确的安装器资产。
- 校验 FSM 资产的
FsmId是否匹配设计。
不建议策划/TA直接处理:
- 新增底层容器生命周期策略。
- 修改
NestedLifetimeScope/Editor 扫描器这类基础设施代码。 - 在不了解依赖图时调整跨组顺序。
7. 快速排错清单
- 新增模块未生效
- 检查是否实现了
IFeatureInstaller。 - 检查
[FeatureInstaller]的Group是否拼写正确。 - 检查目标
AutoGroupCollectionInstaller.targetGroup是否一致。 - 检查该自动组资产是否被挂到当前 Scope 链路中。
- 运行时报“无法实例化安装器”
- 检查类型是否抽象类。
- 检查是否有可用的无参构造(
Activator.CreateInstance需要)。
- 子 Scope 注入失败
- 检查
NestedLifetimeScope.autoParent/parentScope配置。 - 检查父 Scope 是否先于子 Scope 构建。
- 状态机不触发或拿错实例
- 检查
StateMachineInstaller.stateMachineId。 - 检查触发器/状态机是否使用同一套
Symbol<FsmId>分组常量。
更新日志
2026/4/16 11:07
查看所有更新日志
e4055-Merge pull request #12 from azaneNH37/doc于