본문 바로가기
개발/Unity

[Unity][DOTS] Component WriteGroups

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

 

요 며칠, 기존 프리팹을 ECS Entity로 변환하는 작업을 하고 있다. 단순히 변환 API를 호출하면 끝날 줄 알았는데 그렇지 않았다. 변환하고자 하는 프리팹의 계층 구조가 복잡해서 오브젝트 간 렌더링 순서에 문제가 생긴 것이다. ECS TransformSystem을 제대로 이해해야 해결할 수 있을 것 같은 생각이 들어 아래 문서를 읽기 시작했다.

https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/transform_system.html

 

TransformSystem | Package Manager UI website

TransformSystem Section 1: Non-hierarchical Transforms (Basic) LocalToWorld (float4x4) represents the transform from local space to world space. It is the canonical representation and is the only component and can be relied upon to communicate local space

docs.unity3d.com

한참 읽다 보니 WriteGroup라는 말이 계속 나온다. 뭔지 몰라서 일단 넘어가려고 했는데 그래서는 문서를 제대로 읽을 수가 없었다. 그래서 다시 아래의 WriteGroup 문서를 읽기 시작했다.

https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/ecs_write_groups.html

 

WriteGroups | Package Manager UI website

WriteGroups A common ECS pattern is for a system to read one set of input components and write to another, output component. However, you may want to override that system and update the output component based on your own set of inputs. WriteGroups allow yo

docs.unity3d.com

여기까지가 이 포스팅을 쓰는 이유다. 서론이 참 길었다. WriteGroup이라는 개념이 왜 만들어졌는지를 알려면 다시 Component Groups 문서의 Query options 항목을 봐야 한다.

https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/component_group.html#query-options

 

Querying for data using a EntityQuery | Package Manager UI website

Querying for data using a EntityQuery The first step to reading or writing data is finding that data. Data in the ECS framework is stored in components, which are grouped together in memory according to the archetype of the entity to which they belong. To

docs.unity3d.com

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만 다시 설정하면 된다. 끝. 

반응형

댓글