요 며칠, 기존 프리팹을 ECS Entity로 변환하는 작업을 하고 있다. 단순히 변환 API를 호출하면 끝날 줄 알았는데 그렇지 않았다. 변환하고자 하는 프리팹의 계층 구조가 복잡해서 오브젝트 간 렌더링 순서에 문제가 생긴 것이다. ECS TransformSystem을 제대로 이해해야 해결할 수 있을 것 같은 생각이 들어 아래 문서를 읽기 시작했다.
https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/transform_system.html
한참 읽다 보니 WriteGroup라는 말이 계속 나온다. 뭔지 몰라서 일단 넘어가려고 했는데 그래서는 문서를 제대로 읽을 수가 없었다. 그래서 다시 아래의 WriteGroup 문서를 읽기 시작했다.
https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/ecs_write_groups.html
여기까지가 이 포스팅을 쓰는 이유다. 서론이 참 길었다. WriteGroup이라는 개념이 왜 만들어졌는지를 알려면 다시 Component Groups 문서의 Query options 항목을 봐야 한다.
https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/component_group.html#query-options
ECS System은 개별 Entity를 모르기 때문에 query를 통해 특정 Component가 포함된 Entity 리스트를 얻는다. query가 좀 복잡한 경우, EntityQueryDesc를 사용하는데 이때 여러 가지 옵션을 줄 수 있다. 이 옵션 중에서 하나가 바로 WriteGroup이다.
var queryDescription = new EntityQueryDesc
{
All = new ComponentType[] {typeof(A), typeof(B)},
Options = EntityQueryOptions.FilterWriteGroup
};
m_Query = GetEntityQuery(queryDescription);
위 코드와 같이 Options로 EntityQueryOptions.FilterWriteGroup를 사용하면 된다. 그러면 WriteGroup에 포함된 Component 중 query에 명시된 Component를 포함하는 Entity만 추출된다. 말이 좀 복잡한데 예제를 통해 다시 살펴보자.
public struct C1: IComponentData{}
[WriteGroup(C1)]
public struct C2: IComponentData{}
[WriteGroup(C1)]
public struct C3: IComponentData{}
// create entity
EntityManager.CreateEntity(typeof(C1), typeof(C2)); // entity #1
EntityManager.CreateEntity(typeof(C1), typeof(C3)); // entity #2
EntityManager.CreateEntity(typeof(C1), typeof(C2), typeof(C3)); // entity #3
// ... In a system:
var query = new EntityQueryDesc{
All = new ComponentType{typeof(C1), ComponentType.ReadOnly<C3>()},
Options = EntityQueryDescOptions.FilterWriteGroup
};
var m_group = GetEntityQuery(query);
WriteGroup에 C2, C3가 들어있다. query의 All 부분을 보면 WriteGroup 중 C3만 명시돼 있다. 따라서 query의 결과인 m_group에 entity #2만 들어간다. entity #2는 WriteGroup 중 C3는 갖고 있고, C2는 갖지 않는다 (물론 Entity가 Component를 포함한다는 말은 잘못된 말이지만 이번만 이해해 주시길). 만약 query에서 Options로 WriteGroup을 사용하지 않았다면 m_group에 #3도 들어갈 것이다.
사실 위의 경우, WriteGroup 대신 다음과 같이 Options 없이 None을 사용해도 query 결과는 같다.
All = new ComponentType{typeof(C1), ComponentType.ReadOnly<C3>()},
None = new ComponentType[]{ typeof(C2) }
그런데도 WriteGroup은 존재 이유가 있다. WriteGroup을 사용하면 query 조건(특정 Component를 넣고 빼는)이 바뀌어도 ECS System 클래스 코드를 변경할 필요가 없기 때문이다. 단순히 WriteGroup만 다시 설정하면 된다. 끝.
'개발 > Unity' 카테고리의 다른 글
[Unity] Mac에 유니티 캐쉬 서버 설치하기 (0) | 2019.07.19 |
---|---|
[Unity][DOTS] World와 ComponentSystemGroup (0) | 2019.07.12 |
[Unity] hierarchy 창에서 선택한 오브젝트 선택 유지하기 (0) | 2019.06.28 |
[Unity][DOTS] ECS & C# Job System, 샘플 프로젝트 따라잡기 #2 (2) | 2019.03.29 |
[Unity][DOTS] Entity Debugger 사용 방법 (0) | 2019.03.27 |
댓글