VContainer-about/what-is-vcontainer | 概述——VContainer 是什么?
VContainer
import {BenchmarkGraph} from "../../src/components/BenchmarkGraph"
import {GCAllocGraph} from "../../src/components/GCAllocGraph"
专为 Unity 引擎设计的超快 DI 解决方案。"V" 代表将 Unity 的初始 "U" 变得更轻量化、更坚固!
- 极速解析: 基础性能比 Zenject 快 5-10 倍。
- 零 GC 分配: 解析过程中(除实例生成外)完全实现了零内存分配。
- 精简架构: 少量内部类型与 .callvirt 调用。
- 规范 DI 实践: 提供简单透明的 API,谨慎选择功能特性,防止 DI 声明过度复杂化。
- 不可变容器: 线程安全和健壮性。
功能
- 构造函数注入 / 方法注入 / 属性和字段注入
- 纯 C# 类作为入口点自管理 PlayerLoopSystem 调度
- 灵活作用域管理
- 应用程序可以自由创建嵌套的生命周期作用域,支持异步。
- 支持 Roslyn 源代码生成器的加速模式
- 诊断窗口
- 集成 UniTask
- 集成 ECS beta
Unity 中的 DI + 控制反转

DI 容器可以将纯 C# 类作为入口点(而不是 MonoBehaviour)。这意味着业务逻辑的控制流可以与作为视图组件的 MonoBehaviour 实现分离。
扩展阅读:
性能表现
10,000 次迭代的基准测试结果(Unity 2019.x / IL2CPP Standalone macOS)
- 默认情况下,VContainer 和 Zenject 都在运行时使用反射。
- "VContainer (CodeGen)" :通过 ILP PostProcessor 预生成注入方法的 IL 代码进行优化,详见 优化 部分。
复杂解析场景 GC 分配对比(Unity Editor 分析)
基础用法
首先,创建一个作用域。在这里注册的类型会自动解析引用。
public class GameLifetimeScope : LifetimeScope
{
protected override void Configure(IContainerBuilder builder)
{
builder.RegisterEntryPoint<ActorPresenter>();
builder.Register<CharacterService>(Lifetime.Scoped);
builder.Register<IRouteSearch, AStarRouteSearch>(Lifetime.Singleton);
builder.RegisterComponentInHierarchy<ActorsView>();
}
}
相关类定义:
public interface IRouteSearch // 服务接口
{
}
public class AStarRouteSearch : IRouteSearch // 具体实现
{
}
public class CharacterService
{
readonly IRouteSearch routeSearch;
public CharacterService(IRouteSearch routeSearch) // 自动注入
{
this.routeSearch = routeSearch;
}
}
public class ActorsView : MonoBehaviour // 场景组件
{
}
public class ActorPresenter : IStartable // 入口类
{
readonly CharacterService service;
readonly ActorsView actorsView;
public ActorPresenter(
CharacterService service,
ActorsView actorsView)
{
this.service = service;
this.actorsView = actorsView;
}
void IStartable.Start()
{
// 通过 VContainer PlayerLoopSystem 调度 Start()
}
}
- 示例中,当解析 CharacterService 时,CharacterService 的 routeSearch 会自动解析为 AStarRouteSearch 实例。
- VContainer 支持纯 C# 类作为入口点(可指定 Start/Update 等生命周期),实现"业务逻辑与表现层分离"。
异步灵活作用域
LifetimeScope 支持动态创建子作用域,轻松应对游戏中的异步资源加载:
public void LoadLevel()
{
// ... 加载一些资源
// 创建子作用域
instantScope = currentScope.CreateChild();
// 使用 LifetimeScope 预制件创建子作用域
instantScope = currentScope.CreateChildFromPrefab(lifetimeScopePrefab);
// 创建带有额外注册的子作用域
instantScope = currentScope.CreateChildFromPrefab(
lifetimeScopePrefab,
builder =>
{
// 额外注册 ...
});
instantScope = currentScope.CreateChild(builder =>
{
// 额外注册 ...
});
instantScope = currentScope.CreateChild(extraInstaller);
}
public void UnloadLevel()
{
instantScope.Dispose();
}
附加场景加载时建立作用域父子关系:
class SceneLoader
{
readonly LifetimeScope currentScope;
public SceneLoader(LifetimeScope currentScope)
{
currentScope = currentScope; // 注入该类所属的 LifetimeScope
}
IEnumerator LoadSceneAsync()
{
// 在此块中生成的 LifetimeScope 将以 `this.lifetimeScope` 为父级
using (LifetimeScope.EnqueueParent(currentScope))
{
// 如果此场景有 LifetimeScope,其父级将是 `parent`。
var loading = SceneManager.LoadSceneAsync("...", LoadSceneMode.Additive);
while (!loading.isDone)
{
yield return null;
}
}
}
// UniTask 示例
async UniTask LoadSceneAsync()
{
using (LifetimeScope.EnqueueParent(parent))
{
await SceneManager.LoadSceneAsync("...", LoadSceneMode.Additive);
}
}
}
// 在此块中生成的 LifetimeScope 将额外注册。
using (LifetimeScope.Enqueue(builder =>
{
// 为尚未加载的下一个场景注册
builder.RegisterInstance(extraInstance);
}))
{
// 加载场景...
}
更多信息参见 作用域。
UniTask
public class FooController : IAsyncStartable
{
public async UniTask StartAsync(CancellationToken cancellation)
{
await LoadSomethingAsync(cancellation);
await ...
...
}
}
builder.RegisterEntryPoint<FooController>();
更多信息参见 集成。
诊断窗口

更多信息参见 诊断。

浙公网安备 33010602011771号