- 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) - 어제와 내일의 나 그 사이의 이야기