### **VContainer + ECS (beta)** - **목표:** Unity의 ECS와 VContainer의 DI 컨테이너를 함께 사용하여 엔티티 중심 디자인과 의존성 주입을 통합합니다. - **주의사항:** - 현재(문서 기준) Unity 2019.3 이상 버전이 필요합니다. - ECS는 여전히 프리뷰(Preview) 버전이므로, Unity Package Manager에서 "Show preview packages" 옵션을 활성화해야 할 수 있습니다. - **통합 활성화:** 프로젝트에 `com.unity.entities` 패키지가 설치되어 있으면, `VCONTAINER_ECS_INTEGRATION` 컴파일러 심볼이 자동으로 정의되고 ECS 관련 기능이 활성화됩니다. ### **Unity의 기본 월드(Default World) 사용 시** Unity ECS는 기본적으로 `ComponentSystemBase`를 상속하는 시스템 클래스를 자동으로 인스턴스화하고 기본 월드에 추가하여 실행합니다. VContainer는 이 과정에 의존성 주입을 추가할 수 있습니다. - **메서드 주입(Method Injection) 사용:** - ECS 시스템은 Unity에 의해 자동으로 생성되므로, 생성자 주입(Constructor Injection)은 사용할 수 없습니다. 대신 `[Inject]` 어트리뷰트를 사용하여 메서드 주입을 사용해야 합니다. - **코드 예시:** C# ``` class SystemA : SystemBase { [Inject] // 메서드 주입 public void Construct(Settings settings) { // Settings 객체가 VContainer를 통해 주입됩니다. } protected override void OnUpdate() { // 시스템 업데이트 로직 } } // LifetimeScope의 Configure 메서드에서 등록 builder.RegisterSystemFromDefaultWorld<SystemA>(); // 다른 시스템들도 동일하게 등록할 수 있습니다. // builder.RegisterSystemFromDefaultWorld<SystemB>(); // builder.RegisterSystemFromDefaultWorld<SystemC>(); ``` - **설명:** `RegisterSystemFromDefaultWorld<T>()` 메서드를 사용하여 `SystemBase`를 상속하는 시스템을 VContainer에 등록합니다. 이렇게 하면 VContainer는 해당 시스템이 필요로 하는 다른 의존성(예: `Settings`)을 `[Inject]` 어트리뷰트가 붙은 메서드를 통해 주입해줍니다. ### **커스텀 월드(Custom World) 사용 시** VContainer는 새로운 월드를 생성하고, 그 월드에 시스템을 등록하는 기능도 제공합니다. - **월드 생성 및 시스템 등록:** C# ``` // 월드 생성 및 시스템 등록 builder.RegisterNewWorld("My World 1", Lifetime.Scoped) // "My World 1" 이름으로 새로운 월드 생성 .RegisterSystemIntoWorld<SystemA>("My World 1") // My World 1에 SystemA 등록 .RegisterSystemIntoWorld<SystemB>("My World 1"); // My World 1에 SystemB 등록 ``` - **월드와 시스템의 라이프타임:** - **World:** `RegisterNewWorld`를 통해 생성된 월드의 라이프타임은 해당 `LifetimeScope`와 동일합니다. - **System:** `Lifetime.Singleton`으로 등록된 시스템은 해당 월드의 라이프타임과 같습니다. `Lifetime.Scoped`로 등록된 시스템은 해당 스코프가 파괴될 때 `Dispose`가 호출됩니다. - **시스템의 의존성 주입 (생성자 주입):** - 커스텀 월드에 등록하는 시스템은 생성자 주입을 지원합니다. 이는 일반 C# 클래스와 유사하게 의존성을 주입받을 수 있음을 의미합니다. - **코드 예시 (커스텀 월드 및 시스템 생성자 주입):** C# ``` public class SystemA : SystemBase, IDisposable { private readonly Foo _foo; // VContainer를 통해 주입될 의존성 public SystemA(Foo foo) // 생성자 주입 { _foo = foo; UnityEngine.Debug.Log(quot;SystemA created with Foo: {_foo}"); } protected override void OnCreate() { // 엔티티 설정 및 생성 (예시) var archtype = World.EntityManager.CreateArchetype(typeof(ComponentDataA)); World.EntityManager.CreateEntity(archtype); } protected override void OnUpdate() { // ECS 쿼리 및 로직 Entities.ForEach((ref ComponentDataA data) => { // _foo를 사용하여 로직 수행 }) .Schedule(); } public void Dispose() { // 스코프가 파괴될 때 호출됩니다. UnityEngine.Debug.Log("SystemA Disposed"); } } public class GameLifetimeScope : LifetimeScope { protected override void Configure(IContainerBuilder builder) { builder.Register<Foo>(Lifetime.Singleton); // Foo를 등록 builder.UseNewWorld("My World 1", Lifetime.Scoped, systems => // 새로운 월드 생성 { systems.Add<SystemA>(); // SystemA를 이 월드에 추가 (생성자 주입이 적용됨) }); } } ``` - **`builder.UseNewWorld(...)`:** 이 람다 표현식 내에서 `systems.Add<SystemA>()`와 같이 시스템을 추가하면 해당 시스템의 생성자에 VContainer가 등록된 의존성(`Foo`)을 주입해줍니다. ### **월드 해결(Resolving World)** VContainer 컨테이너에서 `World` 객체를 직접 해결(resolve)할 수도 있습니다. - **단일 월드 등록 시:** C# ``` class ClassA { public ClassA(World world) { /* ... */ } // 단일 World 객체를 주입받음 } ``` - **여러 월드 등록 시:** C# ``` class ClassA { public ClassA(IEnumerable<World> worlds) { /* ... */ } // 등록된 모든 World 객체를 컬렉션으로 주입받음 } ``` - 이 기능은 여러 ECS 월드가 있고, 특정 서비스나 컨트롤러가 이 모든 월드에 접근해야 할 때 유용합니다. ### 요약 VContainer가 Unity의 ECS와 통합되어 시스템의 의존성을 관리하고, 기본 월드 또는 커스텀 월드에 시스템을 등록하는 방법을 제공한다고 설명합니다. 특히 커스텀 월드 사용 시에는 시스템의 생성자 주입까지 지원하여 DI의 이점을 ECS에까지 확장할 수 있습니다. 이를 통해 더 복잡하고 모듈화된 Unity ECS 애플리케이션을 구축할 수 있도록 돕습니다. --- 이전 : [[5.4 MessagePipe]] | 다음 : [[6.1 Lifetime Overview]]