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 |