Unity DOTS ECS 심화
DOTS ECS 핵심 개념 복습
섹션 제목: “DOTS ECS 핵심 개념 복습”DOTS(Data-Oriented Technology Stack) ECS는 데이터(Component)와 로직(System)을 분리해 캐시 친화적 메모리 레이아웃을 구성합니다.
- Entity: 고유 ID만 가진 경량 식별자
- Component: 순수 데이터 구조체 (
IComponentData) - System: 컴포넌트를 처리하는 로직 단위
- Archetype: 동일한 컴포넌트 조합 → 같은 Chunk에 연속 배치
IComponentData 설계 원칙
섹션 제목: “IComponentData 설계 원칙”// 작고 단순하게 — 하나의 관심사만public struct Health : IComponentData { public float Value; public float Max;}
public struct Velocity : IComponentData { public float3 Linear; public float3 Angular;}
// 태그 컴포넌트: 데이터 없이 분류만public struct IsEnemy : IComponentData {}public struct IsDead : IComponentData {}컴포넌트는 Blittable 타입(포인터·참조 없음)이어야 Chunk에 연속 배치됩니다.
ISystem vs SystemBase
섹션 제목: “ISystem vs SystemBase”// ISystem: 비관리(unmanaged), 성능 최우선public partial struct MovementSystem : ISystem { public void OnUpdate(ref SystemState state) { foreach (var (velocity, transform) in SystemAPI.Query<RefRO<Velocity>, RefRW<LocalTransform>>()) { transform.ValueRW.Position += velocity.ValueRO.Linear * SystemAPI.Time.DeltaTime; } }}
// SystemBase: 관리(managed), 코루틴/MonoBehaviour 연동 시public partial class SpawnSystem : SystemBase { protected override void OnUpdate() { // Entities.ForEach 또는 Job 활용 }}ISystem은 Burst 컴파일 가능하고 오버헤드가 낮습니다. 새 코드는 ISystem을 권장합니다.
Burst + IJobChunk
섹션 제목: “Burst + IJobChunk”[BurstCompile]public partial struct PhysicsJob : IJobEntity { public float DeltaTime;
public void Execute(ref LocalTransform transform, in Velocity vel) { transform.Position += vel.Linear * DeltaTime; }}
public partial struct PhysicsSystem : ISystem { [BurstCompile] public void OnUpdate(ref SystemState state) { var job = new PhysicsJob { DeltaTime = SystemAPI.Time.DeltaTime }; job.ScheduleParallel(); }}IJobEntity는 소스 제너레이터가 Archetype 쿼리와 Chunk 순회 코드를 자동 생성합니다.
EntityQuery와 필터링
섹션 제목: “EntityQuery와 필터링”EntityQuery _query;
public void OnCreate(ref SystemState state) { _query = SystemAPI.QueryBuilder() .WithAll<Health, Velocity>() .WithNone<IsDead>() .WithChangeFilter<Health>() // Health가 변경된 Chunk만 .Build();}WithChangeFilter는 변경된 Chunk만 처리해 불필요한 순회를 줄입니다.
Baking 워크플로우
섹션 제목: “Baking 워크플로우”씬의 MonoBehaviour를 ECS 데이터로 변환합니다.
// Authoring 컴포넌트 (MonoBehaviour)public class HealthAuthoring : MonoBehaviour { public float MaxHealth = 100f;}
// Baker: 에디터/빌드 시 변환class HealthBaker : Baker<HealthAuthoring> { public override void Bake(HealthAuthoring authoring) { var entity = GetEntity(TransformUsageFlags.Dynamic); AddComponent(entity, new Health { Value = authoring.MaxHealth, Max = authoring.MaxHealth, }); }}SharedComponent로 일괄 렌더링
섹션 제목: “SharedComponent로 일괄 렌더링”// 같은 Material을 공유하는 Entity를 동일 Chunk에 모음public struct RenderMaterial : ISharedComponentData, IEquatable<RenderMaterial> { public Material Value; public bool Equals(RenderMaterial other) => Value == other.Value; public override int GetHashCode() => Value.GetHashCode();}동일 ISharedComponentData 값을 가진 Entity는 같은 Chunk에 배치되어 GPU 인스턴싱 배치 효율이 높아집니다.
IComponentData는 작고 Blittable하게 설계해 Chunk 연속성 유지- 신규 시스템은
ISystem+IJobEntity+[BurstCompile]조합 권장 EntityQuery의WithChangeFilter로 불필요한 순회 차단- Baking으로 MonoBehaviour 기반 씬 설계와 ECS 런타임 분리
ISharedComponentData로 동일 재질 오브젝트를 같은 Chunk에 모아 인스턴싱 최적화