- 4. 여러 종류의 Component
4. 여러 종류의 Component
(5) Dynamic buffer components
https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/components-buffer.html
1) Dynamic buffer 구성 요소 소개
https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/components-buffer-introducing.html
Dynamic buffer components는 관리되지 않는 구조체들의 크기 조절이 가능한 배열처럼 작동하는 컴포넌트
예를 들어 Entity가 이동할 경로점(waypoint) 위치들과 같은 배열 데이터를 저장하는 데 사용할 수 있음
Dynamic buffer의 구성 요소
Dynamic buffer는 데이터와 함께 길이(Length), 용량(Capacity), 내부 포인터(pointer)를 저장
- 길이 (Length):
buffer 에 저장된 요소의 개수, 처음에는 0이며, 값을 추가할 때마다 증가 - 용량 (Capacity):
buffer 에 저장할 수 있는 요소의 최대 개수
처음에는 내부 버퍼 용량과 동일하게 시작하고, 용량을 설정하여 버퍼 크기를 조정 - 포인터 (Pointer):
Dynamic buffer 데이터의 위치를 나타냄
처음에는 데이터가 Entity의 Chunk 내에 있을 때 null로 설정되며,
Unity가 데이터를 Chunk 밖으로 이동시키면 포인터가 새 배열을 가리키도록 설정됩니다.
Dynamic buffer 용량
Dynamic buffer의 초기 용량은 버퍼가 저장하는 타입에 의해 정의됩니다.
기본적으로 용량은 128바이트에 맞게 설정됩니다.
만약 더 큰 용량이 필요하면 InternalBufferCapacity
속성을 사용하여 커스터마이즈할 수 있습니다.
구조적 변경(Structural Changes)
구조적 변경(Structural Changes) : Entity의 생성, 삭제, 또는 컴포넌트 추가/제거와 같은 작업이 수행될 때 Unity의 ECS 시스템 내부에서 구조적 변화가 발생함
Structural Changes는 Dynamic buffer가 참조하는 배열을 파괴하거나 이동시킬 수 있기 때문에, 구조적 변화 후에는 Dynamic buffer에 대한 Handle이 무효화됩니다.
Structural Changes 후에는 Dynamic buffer를 다시 가져와야 합니다.
예를 들어:
public void DynamicBufferExample(Entity e) { // MyElement 타입의 동적 버퍼를 가져옵니다. DynamicBuffer<MyElement> myBuff = EntityManager.GetBuffer<MyElement>(e); // 이 Structural Changes는 이전에 얻은 DynamicBuffer를 무효화시킵니다. EntityManager.CreateEntity(); // 안전 검사로 인해 버퍼에 대한 읽기/쓰기 작업에서 예외가 발생합니다. var x = myBuff[0]; // Structural Changes 후 동적 버퍼를 다시 가져옵니다. myBuff = EntityManager.GetBuffer<MyElement>(e); var y = myBuff[0]; }
네이티브 컨테이너와의 비교
Dynamic buffer는 네이티브 컨테이너가 컴포넌트에서 사용하는 작업 스케줄링 제한이 없으므로, 가능한 경우 코드에서 Dynamic buffer를 사용하는 것이 더 나은 선택입니다.
또한, Dynamic buffer는 Chunk 내에 인라인으로 저장될 수 있어 메모리 대역폭 사용을 줄이는 데 도움을 줍니다.
일반적으로, 여러 Entity가 동일한 컬렉션을 필요로 한다면 Dynamic buffer를 사용하는 것이 좋습니다.
만약 하나의 Entity만 필요하다면 네이티브 컨테이너를 가진 싱글톤 컴포넌트로 처리하는 것이 좋을 수 있습니다.
- Dynamic buffer는 작업 스케줄링 제한이 없고, 메모리 사용 측면에서도 효율적
비교 항목 | 동적 버퍼 (DynamicBuffer<T> ) | NativeContainer (NativeArray<T> , NativeList<T> ) |
---|---|---|
ECS와의 연동 | ✅ Entity에 직접 부착 가능 | ❌ ECS Entity와 직접 연결 불가 |
Job 시스템 사용 | ✅ 가능 (ReadOnly 또는 ParallelForEach 가능) | ✅ 가능 ([NativeContainer] 필요) |
메모리 위치 | Chunk 내 저장 (최적화됨) → 크기 초과 시 자동 이동 | Chunk 외부 할당 |
구조적 변화 영향 | 🚨 구조적 변화 시 무효화됨 → 재할당 필요 | ✅ 영향 없음 |
- 여러 개의 엔티티가 배열 데이터를 가질 필요가 있다면
DynamicBuffer<T>
를 사용하는 것이 좋음 - 싱글톤 데이터처럼 전역적으로 관리할 경우
NativeContainer
를 사용하는 것이 유리함
2) Dynamic buffer 컴포넌트 생성 및 사용 방법
https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/components-buffer-create.html
IBufferElementData를 상속한 구조체 생성
Dynamic buffer의 개별 요소를 정의하는 구조체를 만들고, IBufferElementData
를 상속받아야 합니다.
using Unity.Entities; // Dynamic buffer의 요소가 되는 구조체 정의 // 기본적으로 16개의 요소를 저장할 수 있도록 설정 // 만약 16개를 초과하면 Unity가 자동으로 Chunk 외부 메모리로 확장 [InternalBufferCapacity(16)] public struct ExampleBufferComponent : IBufferElementData { public int Value; // 버퍼 요소 값 }
Entity에 Dynamic buffer 추가하기
DynamicBuffer<T>
를 사용하여 엔티티에 동적 버퍼를 추가하고, 값을 삽입
Entity entity = EntityManager.CreateEntity(); DynamicBuffer<ExampleBufferComponent> buffer = EntityManager.AddBuffer<ExampleBufferComponent>(entity); // 데이터 추가 buffer.Add(new ExampleBufferComponent { Value = 10 }); buffer.Add(new ExampleBufferComponent { Value = 20 }); // 현재 길이 확인 (2개 요소가 들어있음) UnityEngine.Debug.Log("Buffer Length: " + buffer.Length);
Dynamic buffer 읽기
Dynamic buffer는 배열처럼 접근할 수 있습니다.
DynamicBuffer<ExampleBufferComponent> buffer = EntityManager.GetBuffer<ExampleBufferComponent>(entity); for (int i = 0; i < buffer.Length; i++) { UnityEngine.Debug.Log("Buffer Element " + i + ": " + buffer[i].Value); }
동적 버퍼에서 요소 제거
요소를 제거할 때는 RemoveAt()
또는 Clear()
를 사용할 수 있습니다.
buffer.RemoveAt(0); // 첫 번째 요소 제거 buffer.Clear(); // 모든 요소 제거
동적 버퍼의 사용 예시
- 웨이포인트(Waypoints) 저장하기
using Unity.Entities; using Unity.Mathematics; // 웨이포인트를 저장하는 동적 버퍼 [InternalBufferCapacity(4)] public struct WaypointBuffer : IBufferElementData { public float3 Position; // 좌표 정보 }
// 엔티티에 웨이포인트 버퍼 추가 Entity entity = EntityManager.CreateEntity(); DynamicBuffer<WaypointBuffer> waypoints = EntityManager.AddBuffer<WaypointBuffer>(entity); // 웨이포인트 추가 waypoints.Add(new WaypointBuffer { Position = new float3(0, 0, 0) }); waypoints.Add(new WaypointBuffer { Position = new float3(1, 0, 0) }); waypoints.Add(new WaypointBuffer { Position = new float3(2, 0, 0) });
- 시스템에서 동적 버퍼 활용
ISystem
을 활용하여 동적 버퍼를 검색하고 처리하는 시스템을 구현
using Unity.Entities; using Unity.Burst; using Unity.Collections; using Unity.Mathematics; [BurstCompile] public partial struct WaypointSystem : ISystem { public void OnUpdate(ref SystemState state) { foreach (var (waypoints, entity) in SystemAPI.Query<DynamicBuffer<WaypointBuffer>>().WithEntityAccess()) { foreach (var waypoint in waypoints) { UnityEngine.Debug.Log("Waypoint Position: " + waypoint.Position); } } } }
3) Dynamic Buffer 용량 설정
https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/components-buffer-set-capacity.html
Dynamic Buffer의 초기 용량 (Default Capacity)
- Dynamic Buffer는 초기 용량을 가지고 있으며, 기본적으로 128바이트 크기로 설정
- 128바이트는
TypeManager.DefaultBufferCapacityNumerator
를 통해 결정 - 예를 들어,
int
(4바이트) 값을 저장하는 버퍼라면 기본적으로 32개의 요소를 저장할 수 있음
Dynamic Buffer의 메모리 저장 방식
초기 상태
- Entity의 아키타입 청크(Archetype Chunk) 내부에 저장됨.
- 일반적인
IComponentData
처럼 빠르게 접근 가능.
버퍼 크기가 초기 용량을 초과할 경우
- Chunk 외부에 새로운 메모리 공간을 할당하고 데이터를 복사함.
- 이후 해당 버퍼는 항상 Chunk 외부 메모리를 사용하게 됨.
- 단점:
- 메모리 할당 비용 증가
- CPU 캐시 효율 저하 (Chunk 내부에 있던 데이터가 캐시에서 빠짐)
- Chunk 내부에 빈 공간(fragmentation)이 생겨서 메모리 낭비 발생
Dynamic Buffer의 내부 용량 설정 (InternalBufferCapacity
)
초기 용량을 커스텀 설정하려면 InternalBufferCapacity
속성을 사용
// 청크 내부에 최대 42개의 요소를 저장 가능 // 43개 이상 추가 시, 자동으로 청크 외부 메모리로 이동됨 [InternalBufferCapacity(42)] public struct MyBufferElement : IBufferElementData { public int Value; }
초기 용량을 0으로 설정하면?
- 버퍼의 모든 데이터가 청크 외부 메모리에 저장됨.
- 버퍼 크기가 계속 변하는 경우 유리 (즉, 초기에 작은 용량을 두지 않음).
[InternalBufferCapacity(0)] public struct MyBufferElement : IBufferElementData { public int Value; }
최적화
- 버퍼 크기를 예상할 수 있다면
InternalBufferCapacity
를 적절히 설정 - 버퍼 크기가 자주 변경되면
InternalBufferCapacity(0)
을 사용하여 메모리 재할당 비용을 줄임
동적으로 용량 조절 (EnsureCapacity & TrimExcess)
- 실행 중에 버퍼 용량을 설정하려면
EnsureCapacity()
사용
DynamicBuffer<MyBufferElement> buffer = entityManager.GetBuffer<MyBufferElement>(entity); buffer.EnsureCapacity(100); // 100개 요소를 저장할 수 있도록 미리 용량 할당
- 불필요한 메모리를 줄이려면
TrimExcess()
사용
buffer.TrimExcess(); // 현재 길이에 맞게 불필요한 메모리 정리
최적화
- 자주
Add()
로 데이터를 추가하는 경우EnsureCapacity()
를 미리 호출하면 성능 향상 - 더 이상 사용하지 않는 메모리를 줄이려면
TrimExcess()
사용
Dynamic Buffer보다 더 나은 대안?
- Dynamic Buffer의 용량 제한이 문제라면, 다음과 같은 대안 고려 가능
- Blob Assets
- 불변(읽기 전용) 데이터를 저장하는 데 적합
- 여러 엔티티가 공유 가능
- 멀티스레딩 접근 가능
NativeContainer
+IComponentData
조합NativeArray<T>
또는NativeList<T>
등을 사용하여 별도로 관리 가능
- Blob Assets
4) Chunk 내 Dynamic Buffer 접근 방법
모든 동적 버퍼를 한 번에 가져오려면 ArchetypeChunk.GetBufferAccessor()
사용
GetBufferAccessor<T>()
는 BufferAccessor<T>
를 반환하며, 이를 통해 Chunk 내 모든 Entity의 버퍼에 접근 가능
필요한 요소
EntityQueryBuilder
로 Entity 쿼리 생성EntityQuery
에서 Chunk 배열(NativeArray<ArchetypeChunk>) 가져오기BufferTypeHandle<T>
을 사용하여 Dynamic Buffer 핸들 생성GetBufferAccessor<T>()
로 Chunk 내 모든 버퍼 가져오기- 반복문을 통해 버퍼 데이터 처리
Dynamic Buffer 접근 시스템 (SystemBase
기반)
using Unity.Burst; using Unity.Collections; using Unity.Entities; [InternalBufferCapacity(16)] // 내부 용량을 16개 요소로 설정 (초과 시 Chunk 외부 메모리로 이동) public struct ExampleBufferComponent : IBufferElementData { public int Value; } public partial class ExampleSystem : SystemBase { protected override void OnUpdate() { // EntityQuery를 생성하여 ExampleBufferComponent를 가진 Entity 필터링 var query = new EntityQueryBuilder(Allocator.Temp) .WithAllRW<ExampleBufferComponent>() // 읽기/쓰기 가능한 버퍼 포함 .Build(EntityManager); // 쿼리를 통해 ArchetypeChunk 배열 가져오기 NativeArray<ArchetypeChunk> chunks = query.ToArchetypeChunkArray(Allocator.Temp); // Chunk 순회하면서 처리 for (int i = 0; i < chunks.Length; i++) { UpdateChunk(chunks[i]); } // 메모리 해제 chunks.Dispose(); } private void UpdateChunk(ArchetypeChunk chunk) { // ExampleBufferComponent에 대한 BufferTypeHandle 가져오기 BufferTypeHandle<ExampleBufferComponent> bufferTypeHandle = GetBufferTypeHandle<ExampleBufferComponent>(); // Chunk에서 BufferAccessor 가져오기 BufferAccessor<ExampleBufferComponent> buffers = chunk.GetBufferAccessor(ref bufferTypeHandle); // Chunk 내 모든 Entity 의 Dynamic Buffer 접근 for (int i = 0, chunkEntityCount = chunk.Count; i < chunkEntityCount; i++) { DynamicBuffer<ExampleBufferComponent> buffer = buffers[i]; // 각 Entity의 동적 버퍼 요소 접근 for (int j = 0; j < buffer.Length; j++) { UnityEngine.Debug.Log($"Buffer Element {j}: {buffer[j].Value}"); } } } }
Dynamic Buffer 접근 시스템 (ISystem
기반)
using Unity.Burst; using Unity.Collections; using Unity.Entities; [InternalBufferCapacity(16)] public struct ExampleBufferComponent : IBufferElementData { public int Value; } [BurstCompile] // 성능 최적화 public partial struct ExampleSystem : ISystem { public void OnUpdate(ref SystemState state) { // EntityQuery를 생성하여 ExampleBufferComponent를 가진 Entity 필터링 EntityQuery query = SystemAPI.QueryBuilder() .WithAllRW<ExampleBufferComponent>() // 읽기/쓰기 가능한 버퍼 포함 .Build(); // 쿼리를 통해 ArchetypeChunk 배열 가져오기 NativeArray<ArchetypeChunk> chunks = query.ToArchetypeChunkArray(Allocator.Temp); // BufferTypeHandle 가져오기 BufferTypeHandle<ExampleBufferComponent> bufferTypeHandle = state.GetBufferTypeHandle<ExampleBufferComponent>(); // 모든 Chunk 순회하면서 Dynamic Buffer 처리 foreach (var chunk in chunks) { UpdateChunk(chunk, ref bufferTypeHandle); } // NativeArray 해제 chunks.Dispose(); } private void UpdateChunk(ArchetypeChunk chunk, ref BufferTypeHandle<ExampleBufferComponent> bufferTypeHandle) { // Chunk에서 BufferAccessor 가져오기 BufferAccessor<ExampleBufferComponent> buffers = chunk.GetBufferAccessor(ref bufferTypeHandle); // Chunk 내 모든 Entity의 Dynamic Buffer 접근 for (int i = 0; i < chunk.Count; i++) { DynamicBuffer<ExampleBufferComponent> buffer = buffers[i]; // 각 Entity의 Dynamic Buffer 요소 접근 for (int j = 0; j < buffer.Length; j++) { UnityEngine.Debug.Log($"Buffer Element {j}: {buffer[j].Value}"); } } } }
5) 여러 Entity에서 동일한 Dynamic Buffer 재사용
https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/components-buffer-reuse.html
여러 Entity에서 동일한 동적 버퍼 사용하기
IJobEntity
내에서 같은 DynamicBuffer를 공유하는 방법- 동일한 동적 버퍼를 여러 엔티티에 적용하는 경우, 메인 스레드에서 먼저 버퍼를 가져온 후 Job에 전달
SystemBase
기반 예제
using Unity.Entities; using Unity.Burst; using Unity.Jobs; public struct MyElement : IBufferElementData { public int Value; } public struct OtherComponent : IComponentData {} public partial class ExampleSystem : SystemBase { protected override void OnUpdate() { // 특정 엔티티에서 DynamicBuffer 가져오기 Entity e = GetSingletonEntity<MyElement>(); DynamicBuffer<MyElement> myBuffer = SystemAPI.GetBuffer<MyElement>(e); // Job에 버퍼 전달하여 여러 엔티티에서 사용 new MyJobEntity { MyBuffer = myBuffer }.Schedule(); } [BurstCompile] public partial struct MyJobEntity : IJobEntity { public DynamicBuffer<MyElement> MyBuffer; public void Execute(in OtherComponent other) { // MyBuffer를 모든 엔티티에서 공유 for (int i = 0; i < MyBuffer.Length; i++) { UnityEngine.Debug.Log($"Shared Buffer Element: {MyBuffer[i].Value}"); } } } }
ScheduleParallel
을 사용할 때 주의할 점
ScheduleParallel
을 사용하면 다중 스레드 환경에서DynamicBuffer
를 직접 수정할 수 없음- EntityCommandBuffer.ParallelWriter를 활용해야 함
- 그러나 구조적 변경(Structural Change)이 발생하면 버퍼가 무효화됨
ScheduleParallel
을 사용할 때 EntityCommandBuffer 활용 예제
protected override void OnUpdate() { Entity e = GetSingletonEntity<MyElement>(); DynamicBuffer<MyElement> myBuffer = SystemAPI.GetBuffer<MyElement>(e); EntityCommandBuffer ecb = new EntityCommandBuffer(Allocator.TempJob); EntityCommandBuffer.ParallelWriter ecbParallel = ecb.AsParallelWriter(); Entities .WithAll<OtherComponent>() .ForEach((Entity entity, int entityInQueryIndex) => { // EntityCommandBuffer를 사용하여 동적 버퍼에 변경 적용 var buffer = ecbParallel.AddBuffer<MyElement>(entityInQueryIndex, entity); buffer.CopyFrom(myBuffer); }).ScheduleParallel(); Dependency.Complete(); ecb.Playback(EntityManager); ecb.Dispose(); }
최적화
- 같은 버퍼를 여러 Entity에서 사용하면 메모리 절약 가능
ScheduleParallel
을 사용할 때는EntityCommandBuffer.ParallelWriter
필요- Dynamic Buffer 변경 시 구조적 변화(Structural Changes) 발생 가능 → 버퍼 재획득 필요
- 캐시 효율을 고려하여 버퍼 크기 최적화 (
InternalBufferCapacity
)
동일한 Dynamic Buffer를 재사용하면 성능과 메모리 사용량을 최적화
6) Job에서 DynamicBuffer 접근 및 활용
https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/components-buffer-jobs.html
Job에서 DynamicBuffer 접근
IJobEntity
에서 여러 엔티티의 Dynamic Buffer를 조회하려면BufferLookup<T>
를 사용해야 함BufferLookup<T>
는 EntityManager에서 Dynamic Buffer를 효율적으로 검색할 수 있도록 하는 Lookup Table
BufferLookup<T>
를 활용한 Job 예제
using Unity.Entities; using Unity.Burst; using Unity.Collections; [InternalBufferCapacity(16)] public struct ExampleBufferComponent : IBufferElementData { public int Value; } [BurstCompile] public partial struct AccessDynamicBufferJob : IJobEntity { // ReadOnly BufferLookup 멤버 변수를 추가 [ReadOnly] public BufferLookup<ExampleBufferComponent> BufferLookup; public void Execute(Entity entity) { if (BufferLookup.HasBuffer(entity)) { DynamicBuffer<ExampleBufferComponent> buffer = BufferLookup[entity]; for (int i = 0; i < buffer.Length; i++) { UnityEngine.Debug.Log($"Entity {entity.Index} - Buffer[{i}] = {buffer[i].Value}"); } } } }
System에서 BufferLookup<T>
관리하기 (ISystem
버전)
public partial struct AccessDynamicBufferFromJobSystem : ISystem { private BufferLookup<ExampleBufferComponent> _bufferLookup; public void OnCreate(ref SystemState state) { _bufferLookup = state.GetBufferLookup<ExampleBufferComponent>(true); } public void OnUpdate(ref SystemState state) { _bufferLookup.Update(ref state); var job = new AccessDynamicBufferJob { BufferLookup = _bufferLookup }; job.ScheduleParallel(); } }
BufferLookup<T>
는 매 프레임 Update()
를 호출해야 최신 데이터를 유지할 수 있음ScheduleParallel()
을 사용하면 여러 Entity에서 병렬 처리 가능
7) EntityCommandBuffer(ECB)에서 DynamicBuffer 수정
ECB(EntityCommandBuffer) 는 미래에 실행될 변경 사항을 기록하는 역할을 하며, DynamicBuffer에 대한 특별한 API를 제공
- SetBuffer<T>() → 버퍼 내용을 덮어씀
- AppendToBuffer<T>() → 기존 버퍼에 요소 추가 (버퍼 없으면 예외 발생)
- AddBuffer<T>() → 버퍼가 없으면 추가 (버퍼가 있으면 SetBuffer처럼 동작)
- RemoveComponent<T>() → 버퍼 제거
using Unity.Entities; using Unity.Collections; public struct MyElement : IBufferElementData { public int Value; } public partial struct ExampleECBSystem : ISystem { public void OnUpdate(ref SystemState state) { var ecb = new EntityCommandBuffer(Allocator.TempJob); Entity entity = SystemAPI.GetSingletonEntity<MyElement>(); Entity otherEntity = SystemAPI.GetSingletonEntity<MyElement>(); // 버퍼 삭제 ecb.RemoveComponent<MyElement>(entity); // 새 버퍼 추가 및 초기화 DynamicBuffer<MyElement> myBuff = ecb.AddBuffer<MyElement>(entity); myBuff.Add(new MyElement { Value = 5 }); myBuff.Add(new MyElement { Value = -9 }); // 기존 버퍼 덮어쓰기 (없으면 예외 발생) DynamicBuffer<MyElement> otherBuf = ecb.SetBuffer<MyElement>(otherEntity); otherBuf.Add(new MyElement { Value = 10 }); // 버퍼에 요소 추가 (버퍼가 없으면 예외 발생) ecb.AppendToBuffer(otherEntity, new MyElement { Value = 12 }); ecb.Playback(state.EntityManager);// Playback()이 호출될 때 실제 변경이 적용됨 ecb.Dispose(); } }
- ECB는
Playback()
이 호출될 때 실제 변경이 적용됨 - SetBuffer<T>() → 기존 버퍼가 없으면 예외 발생
- AppendToBuffer<T>() → 버퍼가 없으면 예외 발생 (안전하게 사용하려면
AddComponent<T>()
선행) - AddBuffer<T>() → 없으면 추가하고, 있으면 기존 내용을 덮어씀
8) Reinterpret()을 이용한 버퍼 변환
https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/components-buffer-reinterpret.html
Reinterpret<T>()
을 사용하면 같은 크기의 다른 타입으로 변환 가능
단, 메모리 크기가 같은 경우에만 가능 (int ↔ float
, struct ↔ int
등)
public partial class ExampleSystem : SystemBase { private void ReinterpretEntitysChunk(Entity e) { DynamicBuffer<MyElement> myBuff = EntityManager.GetBuffer<MyElement>(e); // MyElement의 Value 필드가 int이므로 int 버퍼로 변환 가능 DynamicBuffer<int> intBuffer = myBuff.Reinterpret<int>(); intBuffer[2] = 6; // 동일한 메모리를 참조하므로 myBuff[2]도 변경됨 MyElement myElement = myBuff[2]; Debug.Log(myElement.Value); // 6 } }
Reinterpret<T>()
은 메모리를 공유하므로, 한쪽을 수정하면 다른 쪽도 변경됨
안전성 검토 필수 (struct
내부 메모리 크기를 고려해야 함)
Reinterpret<T>()
를 사용하는 주요 이유
- 데이터 변환 효율성
- 실제 메모리 복사 없이 같은 메모리를 다른 타입으로 해석할 수 있음
- 큰 데이터 셋을 다룰 때 성능상 이점이 큼
- 메모리 할당 오버헤드 방지
- 데이터 호환성
// 예: 네트워크나 파일에서 받은 바이트 데이터를 직접 구조체로 해석 DynamicBuffer<byte> rawData = ...; DynamicBuffer<MyStruct> structData = rawData.Reinterpret<MyStruct>();
- 저수준 최적화
- 예를 들어 float 배열을 int 비트 패턴으로 직접 조작해야 할 때
- SIMD 연산이나 특수한 비트 연산을 수행할 때 유용
- 다양한 데이터 뷰 제공
// 같은 메모리를 다른 관점에서 접근 가능 DynamicBuffer<Vector3> positions = ...; DynamicBuffer<float> rawFloats = positions.Reinterpret<float>();
주의사항:
- 메모리 크기가 정확히 일치해야 함
- 타입 안전성이 깨질 수 있으므로 신중히 사용
- 데이터 정렬(alignment) 고려 필요
핑백: ECS – Component concepts (3) - 어제와 내일의 나 그 사이의 이야기