はじめに
どうも、土鍋です。
これは土鍋ひとり Advent Calendar 2024の1日目の記事です。
現在、ECSでゲームを作ってみているのですが、そのプロジェクトでDIって導入できないのかなーと思い調べたところ、VContainerが対応してくれているようなので、やってみました。
DefaultWorldにおけるDI
テスト用コード
DIで扱えるようにするにはSystemBase継承でSystemを構築する必要があります。
ISystemでは。現状できないようです。(そもそもMonoBehaviorから扱えないので)
public partial class SystemA : SystemBase { protected override void OnUpdate() { } public void TestMessage() { Debug.Log("SystemA"); } }
public partial class SystemB : SystemBase { [Inject] private SystemA _systemA; protected override void OnUpdate() { if (_systemA == null) return; _systemA.TestMessage(); } }
通常時のDIと同様に[Inject]のAttributeをつけるだけでそこに流し込まれます。
LifetimeScope
LifetimeScopeもMonoBehaviorのときと同様、以下のように簡単に記述できます。
このLifetimeScopeはECS管理ではなくMonoBehaviorのGameObjectにアタッチしてください。
public class TestLifetimeScope : LifetimeScope { protected override void Configure(IContainerBuilder builder) { builder.RegisterSystemFromDefaultWorld<SystemA>(); builder.RegisterSystemFromDefaultWorld<SystemB>(); } }
上記は以下のように書き換えることができます。
builder.UseDefaultWorld(systems =>
{
systems.Add<SystemA>();
systems.Add<SystemB>();
});
CustomWorldにおけるDI
自分で作ったWorldに関してDIを行うこともできます。
これによってWorld自体もVContainerに管理させることができるようです。
テスト用コード
public partial class SystemC : SystemBase { readonly ServiceA serviceA; public SystemC(ServiceA serviceA) { this.serviceA = serviceA; } protected override void OnUpdate() { serviceA.TestMessage(); } }
public class ServiceA { public void TestMessage() { Debug.Log("ServiceA"); } }
このような通常のクラスをSystemに流すように扱うことももちろんできる。
LifetimeScope
以下のように記述することで、Worldの生成から登録まで行っています。
builder.RegisterNewWorld("MyWorld", Lifetime.Scoped); builder.RegisterSystemIntoWorld<SystemC>("MyWorld"); builder.Register<ServiceA>(Lifetime.Singleton);