ECS – BufferTypeHandle

ECS – BufferTypeHandle

ECS에서 DynamicBuffer<T>를 처리하려면 BufferTypeHandle<T>를 사용해야 한다.

즉, “IComponentData가 아닌 버퍼 데이터를 읽고/쓰는 Handle

1. BufferTypeHandle<T>란?

  • ECS에서 DynamicBuffer<T>를 읽고/쓰기 위한 Handle
  • IJobChunk 내부에서 사용됨
  • GetBufferAccessor(ref BufferTypeHandle<T>)를 이용해 버퍼 데이터 접근
  • 쓰기 여부에 따라 읽기 전용(true) / 읽기+쓰기(false) 로 설정 가능

2. 사용 예제

1) OnCreate()에서 초기화

_BufferTypeHandle = state.GetBufferTypeHandle<GridCellBufferComponent>(isReadOnly: false);
  • isReadOnly: true → 읽기 전용
  • isReadOnly: false → 읽기 & 쓰기 가능

2) OnUpdate()에서 매 프레임 업데이트

_BufferTypeHandle.Update(ref state);
  • Update(ref state)를 호출해야 최신 데이터를 가져올 수 있다.

3. BufferTypeHandle 상세 사용법

1) 기본 사용법 (IJobChunk에서 사용)

[BurstCompile]
public struct CountJob : IJobChunk
{
    public BufferTypeHandle<GridCellBufferComponent> BufferTypeHandle;

    public void Execute(in ArchetypeChunk chunk, int chunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
    {
        var buffers = chunk.GetBufferAccessor(ref BufferTypeHandle);

        for (int i = 0; i < chunk.Count; i++)
        {
            DynamicBuffer<GridCellBufferComponent> buffer = buffers[i];

            for (int j = 0; j < buffer.Length; j++)
            {
                buffer[j] = new GridCellBufferComponent
                {
                    Position = buffer[j].Position,
                    IsOccupied = buffer[j].IsOccupied,
                    Count = buffer[j].Count + 1 // Count 증가
                };
            }
        }
    }
}
  • chunk.GetBufferAccessor(ref BufferTypeHandle)을 사용하여 DynamicBuffer에 접근
  • chunk에 속한 모든 DynamicBuffer<GridCellBufferComponent>에 대해 반복문 실행

2) OnUpdate()에서 ScheduleParallel 실행

public void OnUpdate(ref SystemState state)
{
    _BufferTypeHandle.Update(ref state);

    var job = new CountJob
    {
        BufferTypeHandle = _BufferTypeHandle
    };

    state.Dependency = job.ScheduleParallel(_GridQuery, state.Dependency);
}
  • _BufferTypeHandle.Update(ref state); → 최신 상태 반영
  • ScheduleParallel() → 여러 개의 chunk를 병렬 실행

3) IJobParallelFor에서 BufferTypeHandle를 사용할 때

일반적으로 IJobParallelFor에서는 직접 사용할 수 없고, AsNativeArray() 를 사용해야 함.

[BurstCompile]
public struct CountJobParallelFor : IJobParallelFor
{
    public NativeArray<GridCellBufferComponent> BufferNativeArray;

    public void Execute(int index)
    {
        BufferNativeArray[index] = new GridCellBufferComponent
        {
            Position = BufferNativeArray[index].Position,
            IsOccupied = BufferNativeArray[index].IsOccupied,
            Count = BufferNativeArray[index].Count + 1
        };
    }
}

OnUpdate()에서 실행:

public void OnUpdate(ref SystemState state)
{
    _BufferTypeHandle.Update(ref state);
    var chunks = _GridQuery.ToArchetypeChunkArray(Allocator.TempJob);

    for (int i = 0; i < chunks.Length; i++)
    {
        BufferAccessor<GridCellBufferComponent> bufferAccessor = chunks[i].GetBufferAccessor(ref _BufferTypeHandle);
        for (int j = 0; j < bufferAccessor.Length; j++)
        {
            DynamicBuffer<GridCellBufferComponent> buffer = bufferAccessor[j];

            var job = new CountJobParallelFor
            {
                BufferNativeArray = buffer.AsNativeArray()
            };

            job.Schedule(buffer.Length, 1).Complete(); // 즉시 실행
        }
    }
    chunks.Dispose();
}

주의할 점

  • DynamicBuffer<T>에서 AsNativeArray() 를 호출하여 IJobParallelFor에서 사용
  • .Complete() 없이 state.Dependency = job.Schedule();을 하면 Write Conflict 에러 발생
  • buffer.AsNativeArray()해당 프레임에서만 유효

4. BufferTypeHandle 요약

기능설명
BufferTypeHandle<T>DynamicBuffer<T>를 읽고/쓰기 위한 Handle
.Update(ref state)매 프레임 최신 상태로 갱신
GetBufferAccessor(ref BufferTypeHandle<T>)DynamicBuffer<T>를 가져오는 함수
ScheduleParallel()여러 chunk를 병렬 실행
AsNativeArray()IJobParallelFor에서 사용 가능

BufferTypeHandle<T>는 언제 사용?

  • 많은 데이터가 DynamicBuffer에 저장될 때
  • ECS에서 IJobChunk 또는 IJobParallelFor을 활용할 때
  • 최대 성능을 끌어내기 위해 ScheduleParallel을 사용할 때

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤