parallel job을 소개합니다.
1. "Scripts/Aspects" 폴더에 "CannonBallAspect.cs"라는 이름의 새 C# 소스 파일을 만들고 아래 코드를 작성합니다.
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
readonly partial struct CannonBallAspect : IAspect
{
    // 관점의 엔티티 필드는 엔티티 자체에 대한 액세스를 제공합니다.
    // 예를 들어 EntityCommandBuffer에 명령을 등록하는 데 필요합니다.
    public readonly Entity Self;
    // Aspect에는 다른 Aspect가 포함될 수 있습니다.
    readonly TransformAspect Transform;
    // RefRW 필드는 Component에 대한 읽기 및 쓰기 액세스를 제공합니다.
    // 측면이 "in" 매개변수로 사용되는 경우 필드는 RefRO인 것처럼 동작하고 쓰기 시도 시 예외를 발생시킵니다.
    readonly RefRW<CannonBall> CannonBall;
    // 이와 같은 속성은 필수가 아니며 대신 Transform 필드를 공개할 수 있습니다.
    // 그러나 "aspect.aspect.aspect.component.value.value"의 체인을 피함으로써 가독성을 향상시킵니다.
    public float3 Position
    {
        get => Transform.LocalPosition;
        set => Transform.LocalPosition = value;
    }
    public float3 Speed
    {
        get => CannonBall.ValueRO.Speed;
        set => CannonBall.ValueRW.Speed = value;
    }
}
2. "Scripts/Systems" 폴더에 "CannonBallSystem.cs"라는 이름의 새 C# 소스 파일을 만들고 아래 코드를 작성합니다.
using Unity.Burst;
using Unity.Entities;
using Unity.Mathematics;
[BurstCompile]
// IJobEntity는 실행 함수의 서명에서 쿼리를 암시적으로 정의하기 위해 소스 생성에 의존합니다.
partial struct CannonBallJob : IJobEntity
{
    // 일반 EntityCommandBuffer는 병렬로 사용할 수 없으며 ParallelWriter를 명시적으로 사용해야 합니다.
    public EntityCommandBuffer.ParallelWriter ECB;
    // Job에서 시간에 직접 액세스할 수 없으므로 DeltaTime을 매개변수로 전달해야 합니다.
    public float DeltaTime;
    // ChunkIndexInQuery 속성은 Chunk Index를 int 매개변수에 매핑합니다.
    // 각 Chunk는 단일 스레드에서만 처리할 수 있으므로 해당 인덱스는 각 스레드에 고유합니다.
    // 발생하는 병렬 처리의 양에 관계없이 완전히 결정적입니다.
    // 따라서 해당 인덱스는 EntityCommandBuffer에 명령을 기록할 때 Sort Key로 사용됩니다.
    // 이렇게 하면 명령 재생이 항상 결정적임을 보장합니다.
    void Execute([ChunkIndexInQuery] int chunkIndex, ref CannonBallAspect cannonBall)
    {
        var gravity = new float3(0.0f, -9.82f, 0.0f);
        var invertY = new float3(1.0f, -1.0f, 1.0f);
        cannonBall.Position += cannonBall.Speed * DeltaTime;
        if (cannonBall.Position.y < 0.0f)
        {
            cannonBall.Position *= invertY;
            cannonBall.Speed *= invertY * 0.8f;
        }
        cannonBall.Speed += gravity * DeltaTime;
        var speed = math.lengthsq(cannonBall.Speed);
        if (speed < 0.1f) ECB.DestroyEntity(chunkIndex, cannonBall.Self);
    }
}
[BurstCompile]
partial struct CannonBallSystem : ISystem
{
    [BurstCompile]
    public void OnCreate(ref SystemState state)
    {
    }
    [BurstCompile]
    public void OnDestroy(ref SystemState state)
    {
    }
    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        var ecbSingleton = SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>();
        var ecb = ecbSingleton.CreateCommandBuffer(state.WorldUnmanaged);
        var cannonBallJob = new CannonBallJob
        {
            // EntityCommandBuffer에 대한 병렬 작성기를 가져오는 데 필요한 함수 호출에 유의하십시오.
            ECB = ecb.AsParallelWriter(),
            // Job에서 시간에 직접 액세스할 수 없으므로 DeltaTime을 매개변수로 전달해야 합니다.
            DeltaTime = SystemAPI.Time.DeltaTime
        };
        cannonBallJob.ScheduleParallel();
    }
}
3. 플레이 모드로 들어가면 대포알이 이제 탱크에서 멀어지고 지면에서 튀고 있습니다.

'Unity Entities Tutorial' 카테고리의 다른 글
| Unity Entities 1.0.0 Tutorial - Step 7. Colored tanks and cannon balls (0) | 2023.01.29 | 
|---|---|
| Unity Entities 1.0.0 Tutorial - Step 6. Spawning many tanks (0) | 2023.01.29 | 
| Unity Entities 1.0.0 Tutorial - Step 4. Cannon Balls (1) | 2023.01.28 | 
| Unity Entities 1.0.0 Tutorial - Step 3. Tank movement (0) | 2023.01.28 | 
| Unity Entities 1.0.0 Tutorial - Step 2. Turret Rotation (0) | 2023.01.28 | 
