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을 사용할 때

