### **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]]