본문 바로가기
개발/Unity

[Unity][DOTS] World와 ComponentSystemGroup

by 가리봉맨 2019. 7. 12.
반응형

기본적으로 System은 클래스 코드만 작성하면 ECS가 알아서 인스턴스를 생성하고, World에 추가하고, 매 프레임에 업데이트까지 시켜준다. 그런데 프로젝트 진행 중 System을 앱 실행 시점이 아닌 특정 시점에 생성 및 업데이트시켜야 하는 상황이 생겼다. 즉, 앞에서 언급한 프로세스를 수동으로 해야 한다는 뜻이다. 자료를 찾다 보니 Unity 홈페이지 매뉴얼보다 잘 쓴 블로그 포스트(https://gametorrahod.com/world-system-groups-update-order-and-the-player-loop/)를 발견했다. 포스트 앞부분에 내가 원하는 내용이 모두 들어있어서 그대로 번역해봤다.

ECS를 이미 사용해봤다면 "default world"라는 말을 들어본 적이 있을 것이다. C# 코드로 작성한 System은 유니티 에디터에서 Play 버튼을 누르는 순간, 자동으로 업데이트된다. 이 포스트에서는 이 동작을 역(reverse)으로 파헤쳐 볼 것이다. 자동 업데이트는 잠시 잊어버리자. 그러는 편이 "default world"를 쉽게 이해하는 데에 더 낫다.

World

  • World는 하나의 EntityManager 클래스 객체를 갖는다. EntityManager는 ECS의 핵심(core)적인 기능을 강력한 데이터베이스 형태로 갖는다.
  • World는 ComponentSystem, JobComponentSystem, EntityCommandBufferSystem, ComponentSystemGroup 같은 System을 포함한다. System은 자신이 속한 World의 EntityManager를 알고 있다. 그 덕분에 EntityManager로부터 Entity를 얻어 올 수 있고, Entity로 무슨 작업을 할 것인지에 대한 로직을 갖는다. World 클래스의 GetOrCreateSystem() 메서드를 이용해서 System을 만들 수 있다. 이 시점에 World는 자기 자신을 System에 삽입한다.
  • System 클래스는 자신 자신의 World를 참조하기 위해 World와 EntityManger 프로퍼티(property)를 갖는다.

문제점

  • System은 일반적으로 override한 OnUpdate() 메서드에 로직을 구현한다. System의 OnUpdate()는 System 인스턴스의 Update() 호출에 의해 트리거(trigger)가 발동돼서 작동한다. 하지만 이런 방식은 World 인스턴스의 GetOrCreateSystem() 메서드로 System들을 생성한 후에 순차적으로 Update()를 호출해야 하기 때문에 상당히 불편하다. 그리고 System들 간에 어떤 순서에 의해 순차적으로 호출해야 하는지도 명확하지 않다.
  • World는 갖고 있는 전체 System을 한꺼번에 업데이트하는 메서드를 제공하지 않는다.

ComponentSystemGroup

  • 해결책은 "순서가 정해진 일괄 업데이트"다. ComponentSystemGroup(이하 group)은 System 인스턴스의 Update() 메서드 호출, override를 위한 OnUpdate() 메서드, System을 World에 추가하는 기능 등을 포함하고 처리한다.
  • group은 수많은 System을 갖는다. System뿐 아니라 다른 group도 가질 수 있다. 또한 갖고 있는 System들을 순서에 따라 한꺼번에 업데이트할 수 있다. 이것은 World가 할 수 없는 작업이다. 얼마나 많은 System을 갖고 있는지에 상관없이 이 group을 실행하기만 하면 된다.
  • group에 system을 추가하려면 AddSystemToUpdateList() 메서드를 호출한다. group의 Update() 메서드를 호출하면 어떤 방식으로 system을 group에 추가했는지에 따라 순서대로 system들이 업데이트된다.

여기까지 일단 번역 끝.

직역을 하다보니 좀 복잡해 보이는데 별 거 없다. 위 번역에는 빠졌지만 작성한 System 클래스 이름 위에 [DisableAutoCreation] 어트리뷰트(attribute)를 추가해야 한다. 그래야 자동으로 System이 생성되지 않는다. 그리고 만들어지기 원하는 시점에 GetOrCreateSystem() 메서드를 호출하면 된다. 그리고 ComponentSystemGroup을 생성하거나 기본 제공되는 것을 가져온다. 마지막으로 AddSystemToUpdateList() 메서드로 system을 추가하면 system이 업데이트된다.

진짜 끝.

반응형

댓글