Unity DOTS/ECS Sample Projtect

ECS SampleProject #7 IJobEntity

개양반 2022. 7. 31.

원래 7번은 7. IJobChunkStructBased 이지만 최근 버전에서는 IJobChunkStructBased가 IJobEntityBatch로 대체되어 건너뛰고 IJobEntity로 바로 넘어갑니다.

또한 9. ForEach_ISystem는 BurstCompile을 할 수 있는 구조체를 사용하는 예제인데 최신 버전부터 SystemBase의 OnUpdate에서도 구조체의 경우 BurstComplie을 사용할 수 있게 되었으므로,  9. ForEach_ISystem도 생략합니다.

 

선행 학습

[Unity DOTS/Dots Custom Manual] - UNITY DOTS - IJobEntity Jobs 에 대해 알아보자

 

이전 글 보기

[Unity DOTS/ECS Sample Projtect] - ECS Sample Project #1 ForEach

[Unity DOTS/ECS Sample Projtect] - ECS Sample Project #2 IJobEntityBatch

[Unity DOTS/ECS Sample Projtect] - ECS Sample Project #3 Sub Scene

[Unity DOTS/ECS Sample Projtect] - ECS Sample Project #4 SpawnFromMonoBehaviour

[Unity DOTS/ECS Sample Projtect] - ECS Sample Project #5 SpawnFromEntity

[Unity DOTS/ECS Sample Projtect] - ECS Sample Project #6 SpawnAndRemove


오늘 알아볼 내용

오늘은 IJobEntity에 대해 알아볼 겁니다. 그 외 Cube가 빙글빙글 돌아가는 예제일 뿐 특별한 것은 보이지 않습니다.

오늘도 Cube는 빙글빙글 돈다.


새로운 Scene을 만들고 이름을 7. IJobEntity로 변경하고 원하는 폴더에 저장합니다. 7. IJobEntity 폴더를 만들고 자식 폴더로 System, Component를 만듭니다.


Component 만들기

[7. IJobEntity\Component] 폴더에 우클릭 > Create > ECS > Runtime Component Type을 누르고 파일 이름을 RotationSpeed_IJobEntity로 변경한 뒤 아래 코드를 작성합니다.

using Unity.Entities;

[GenerateAuthoringComponent]
public struct RotationSpeed_IJobEntity : IComponentData
{
    public float RadiansPerSecond;
}

System 만들기

[7. IJobEntity\System] 폴더에 우클릭 > Create > ECS > System 을 누르고 파일 이름을 RotationSpeedSystem_IJobEntity로 변경합니다.

 

1. Job 구조체 정의

public partial class RotationSpeedSystem_IJobEntity : SystemBase 위 쪽에 아래의 코드를 작성합니다.

partial struct RotateEntityJob : IJobEntity
{
    public float DeltaTime;

    public void Execute(ref Rotation rotation, in RotationSpeed_IJobEntity speed)
    {
        rotation.Value =
            math.mul(
                math.normalize(rotation.Value),
                quaternion.AxisAngle(math.up(), speed.RadiansPerSecond * DeltaTime));
    }
}

#코드 설명

IJobEntity를 상속받으면 Excute 함수를 구현해야 합니다. Excute함수의 매개변수로 어떤 ComponentData를 반복실행할 것인지 명시해야 합니다. 위 예제에서는 rotation(쓰기가능), RotationSpeed_IJobEntity(읽기)로 명시하여 모든 Entity 중에 명시한 ComponentData타입을 가지고 있는 Entitiy를 조회하고 명시한 ComponentData를 가져옵니다. 

ForEach의 람다함수로 Query를 작성한 것과 비슷합니다.

 

2. System 작성

위의 구조체 밑에 아래의 코드를 작성합니다.

public partial class RotationSpeedSystem_IJobEntity : SystemBase
{
    protected override void OnUpdate()
    {
    	// NativeArray 초기화 배열크기, 메모리 할당
        NativeArray<Translation> test = new NativeArray<Translation>(3, Allocator.TempJob);
        
        // 구조체 생성 후 실행 예약
        new RotateEntityJob { DeltaTime = Time.DeltaTime }.ScheduleParallel();

        // 메모리 할당 해제
        test.Dispose();
    }
}

#코드 설명

1. new NativeArray<Translation>(3, Allocator.TempJob);

Job에서 사용할 NativeArray는 4프레임동안 유지되는 Allocator.TempJob 또는 Allocator.Persistent를 사용해야 합니다.

 

2. new RotateEntityJob { DeltaTime = Time.DeltaTime }.ScheduleParallel();

IJobEntity 구조체를 생성하고 필드값을 전달한 후 실행을 예약합니다. Query를 전달하지 않았으므로 IJobEntity의 Excute의 매개함수에서 Query로 조회된 모든 Entity의 rotation 값을 변경합니다. 만약, Job을 Schedule할때 Query를 전달하면 Quey로 조회된 Entity 중에 Excute의 매개변수에 명시된 ComponentData를 가진 Entity의 ComponentData만 수정합니다. 

    // m_QueryBoidTarget로 조회한 Entity의 Component만 QueryJob에서 반복 실행됩니다.
    new QueryJob().ScheduleParallel(m_QueryBoidTarget);

 


테스트 환경 만들기

Cube 두개를 만들고 자식, 부모 관계로 만들어줍니다. 아래의 이미지처럼 포개 놓습니다. RotationSpeed_IJobEntity를 추가하고 ConvertToEntity를 활성화시킵니다.


재생 버튼을 눌러 IJobEntity를 제대로 구현했는지 확인합니다.

댓글

💲 추천 글