샘플 프로젝트는 https://github.com/Unity-Technologies/EntityComponentSystemSamples 에서 받아볼 수 있다.
샘플 프로젝트의 예제는 총 일곱 개다. HelloECS 폴더에 여섯 개, Advanecd 폴더 아래 한 개가 들어있다. HelloECS 여섯 개 예제 중 첫 번째 예제인 HelloCube_01_ForEach 씬(scene)를 파헤쳐 보겠다.
Project 뷰를 보면 아래 그림과 같이 HelloCube_01_ForEach 폴더 안에 씬, README 문서, 세 개의 C# 스크립트가 들어있다.
README 파일의 내용만으로 이 예제의 전체 구조와 동작을 파악할 수 있다. ECS의 각 요소인 Entity, Component, System은 번역하지 않고 영어 단어 그대로 쓰겠다. 이 예제는 한 쌍의 큐브가 회전하는 간단한 ECS 시스템을 보여준다. ECS는 데이터(data)와 로직(functionality)을 분리해서 처리하는데, 데이터는 Component에 저장하고 로직은 System으로 구현한다.
ComponentSystem을 상속받아 작성한 RotationSpeedSystem은 Entities.ForEach 구문으로 각 Entity를 반복(iterate) 처리한다. 이 예제에는 Entity가 딱 한 개지만, 더 많은 Entity를 씬에 추가하면 RotationSpeedSystem이 씬에 존재하는 모든 Entity의 데이터를 갱신한다.
public class RotationSpeedSystem : ComponentSystem
{
protected override void OnUpdate()
{
Entities.ForEach((ref RotationSpeed rotationSpeed, ref Rotation rotation) =>
{
var deltaTime = Time.deltaTime;
rotation.Value = math.mul(math.normalize(rotation.Value),
quaternion.AxisAngle(math.up(), rotationSpeed.RadiansPerSecond * deltaTime));
});
}
}
단, 해당 Entity는 RotationSpeed Component를 갖고 있어야 한다.
[Serializable]
public struct RotationSpeed : IComponentData
{
public float RadiansPerSecond;
}
참고로 ComponentSystem은 Entities.ForEach를 메인 쓰레드에서 실행한다. 멀티 코어를 사용하려면 JobComponentSystem을 상속받아 System을 구현해야 한다. 이 부분은 다음 예제인 HelloCube_02_IJobProcessComponentData 에서 확인할 수 있다.
ECS는 ConvertToEntity라는 MonoBehaviour를 제공한다. ConvertToEntity는 기존 방식대로 Hierarchy 창에서 만든 GameObject와 그 자식 오브젝트들을 로딩 시점에 Entity와 Component로 변환한다. 현재 ConvertToEntity는 유니티 빌트인(built-in) MonoBehaviour 중 Transform, MeshRenderer를 변환할 수 있다. 변환된 결과물인 Entity와 Component는 Entity Debugger에서 확인할 수 있다. 아래 그림은 기존 MeshRenderer가 RenderMesh Component로 변환돼서 RenderMeshSystemV2에 의해 처리되는 모습이다. Entity Debugger 사용법은 "[Unity][DOTS] Entity Debugger 사용 방법" 포스트를 참고하시길 바란다.
직접 작성한 MonoBehaviour에 IConvertGameObjectToEntity 인터페이스를 구현하면 ConvertToEntity가 기존 MonoBehaviour의 데이터를 Component로 변환해준다. 이 예제에서는 RotationSpeedProxy MonoBehaviour에서 RotationSpeed Component를 Entity에 추가하기 위해 IConvertGameObjectToEntity 인터페이스를 구현했다.
public class RotationSpeedProxy : MonoBehaviour, IConvertGameObjectToEntity
{
public float DegreesPerSecond;
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
var data = new RotationSpeed { RadiansPerSecond = math.radians(DegreesPerSecond) };
dstManager.AddComponentData(entity, data);
}
}
이 예제의 실행 화면은 다음과 같다. 귀찮아서 GIF 파일로 만들지 않고 스크린샷만 찍었는데 매 프레임마다 RotationSpeedSystem이 RotationSpeed 값을 얻어서 큐브를 Y축 기준으로 회전시킨다.
다음 포스트에서는 HelloECS의 두번째 예제인 HelloCube_02_IJobProcessComponentData를 파헤쳐보겠다.
'개발 > Unity' 카테고리의 다른 글
[Unity][DOTS] Component WriteGroups (8) | 2019.07.05 |
---|---|
[Unity] hierarchy 창에서 선택한 오브젝트 선택 유지하기 (0) | 2019.06.28 |
[Unity][DOTS] Entity Debugger 사용 방법 (0) | 2019.03.27 |
[Unity][DOTS] ECS의 핵심, Archetype과 Chunk (0) | 2019.03.26 |
[Unity][DOTS] 빈(empty) ECS Project 생성하기 (2) | 2019.03.15 |
댓글