유니티 ECS와 GameObject 연동 방법
Unity ECS (Entity Component System) - GameObjects와의 통합 및 마이그레이션
Section titled “Unity ECS (Entity Component System) - GameObjects와의 통합 및 마이그레이션”Unity 6.4부터 Entity Component System(ECS)가 코어 엔진 패키지로 통합되면서, 기존의 GameObject 기반 프로젝트와 ECS를 함께 사용할 수 있게 되었습니다. 이 문서는 ECS의 핵심 개념, GameObject와의 통합 방법, 그리고 실무 적용 전략을 다룹니다.
1. ECS 기본 개념
Section titled “1. ECS 기본 개념”1.1 Entity-Component-System 아키텍처
Section titled “1.1 Entity-Component-System 아키텍처”ECS는 데이터 지향적 설계(Data-Oriented Design) 패턴으로, 세 가지 핵심 개념으로 구성됩니다:
- Entity (엔티티): 게임 객체의 정체성을 나타내는 고유 ID. 데이터 컨테이너 역할을 하며, 자체적으로 동작을 가지지 않습니다.
- Component (컴포넌트): 엔티티에 붙어있는 데이터 구조체. ECS 컴포넌트는 객체지향의 MonoBehaviour와 달리, 순수한 데이터만 저장합니다.
- System (시스템): 컴포넌트의 데이터를 읽고 처리하는 로직. 특정 컴포넌트 조합을 가진 엔티티들을 쿼리하여 배치 처리합니다.
1.2 GameObject와의 차이점
Section titled “1.2 GameObject와의 차이점”| 항목 | GameObject | ECS Entity |
|---|---|---|
| 구조 | 객체지향 (OOP) | 데이터 지향 (Data-Oriented) |
| MonoBehaviour | 데이터 + 동작 혼재 | 데이터만 보유 |
| 처리 방식 | 개별 Update() 호출 | 배치 처리 (시스템) |
| 메모리 배치 | 분산 | 선형 (Cache-friendly) |
| 성능 | 중소 규모 | 대규모 처리에 최적 |
1.3 ECS의 핵심 장점
Section titled “1.3 ECS의 핵심 장점”- 성능 향상: 선형 메모리 배치로 CPU 캐시 효율성 증대
- 확장성: 수천 개의 엔티티도 효율적으로 처리
- 결정론적 실행: 시스템 실행 순서가 명확하여 디버깅이 용이
- 병렬 처리: C# Job System과 Burst Compiler를 활용한 고성능 멀티스레딩
- 메모리 효율: 불필요한 메모리 오버헤드 제거
2. GameObject와 ECS의 통합 전략
Section titled “2. GameObject와 ECS의 통합 전략”2.1 Conversion 시스템
Section titled “2.1 Conversion 시스템”기존의 GameObject 기반 프로젝트를 ECS로 마이그레이션하는 가장 실용적인 방식은 Conversion 시스템입니다:
// GameObject를 Editor에서 설계한 후, 런타임에 ECS 엔티티로 변환// 이 과정은 GameObjectConversionSystem이 자동으로 처리Conversion 과정:
- Scene에 GameObject를 배치
- 특정 Component를 GameObject에 추가 (예:
IConvertGameObjectToEntity) - 게임 실행 시 ConversionSystem이 자동으로 GameObject를 ECS 엔티티로 변환
- 변환된 엔티티는 ECS 시스템에 의해 관리됨
2.2 Hybrid ECS (GameObject + Entity 혼용)
Section titled “2.2 Hybrid ECS (GameObject + Entity 혼용)”Unity 6.4부터는 하이브리드 모드에서 GameObject와 ECS 엔티티를 동시에 사용할 수 있습니다:
using Unity.Entities;using UnityEngine;
// GameObject는 그대로 사용public class PlayerController : MonoBehaviour{ void Update() { // 기존 GameObject 로직 }}
// 동시에 ECS 엔티티도 사용 가능public partial struct PlayerMovementSystem : ISystem{ [BurstCompile] public void OnUpdate(ref SystemState state) { // ECS 기반 대량 데이터 처리 }}이점:
- 기존 코드 유지 가능
- 성능이 필요한 부분부터 ECS로 마이그레이션
- 점진적 전환 가능
2.3 Unified Transforms (통합 트랜스폼)
Section titled “2.3 Unified Transforms (통합 트랜스폼)”Unity 6.4의 큰 변화는 ECS와 GameObject의 트랜스폼을 통합하는 것입니다:
- ECS 엔티티의
LocalTransform컴포넌트와 GameObject의Transform컴포넌트가 동기화 - GameObject 계층 구조를 ECS 엔티티 계층으로 직접 매핑 가능
Parent컴포넌트를 통한 엔티티 간 부모-자식 관계 구현
3. ECS 핵심 API 및 구현
Section titled “3. ECS 핵심 API 및 구현”3.1 LocalTransform 컴포넌트
Section titled “3.1 LocalTransform 컴포넌트”LocalTransform은 엔티티의 상대적 위치, 회전, 스케일을 정의합니다:
using Unity.Transforms;using Unity.Mathematics;
// LocalTransform 생성LocalTransform transform = LocalTransform.FromPosition(1, 2, 3);
// 속성에 직접 접근float3 position = transform.Position;quaternion rotation = transform.Rotation;float scale = transform.Scale;
// 변환 적용 (함수형 - 새로운 값 반환)transform = transform.RotateZ(math.radians(45f));transform.Position += math.up();중요: ECS 트랜스폼은 값 타입이므로, 변경 후 반드시 할당해야 합니다.
3.2 Parent 컴포넌트와 계층 구조
Section titled “3.2 Parent 컴포넌트와 계층 구조”엔티티 계층을 구성하려면:
using Unity.Entities;using Unity.Transforms;
// 자식 엔티티에 Parent 컴포넌트 추가ecb.AddComponent(childEntity, new Parent { Value = parentEntity });
// ParentSystem이 자동으로 실행되어 계층 관계 유지// 주의: 계층이 크면 성능이 저하될 수 있음성능 최적화 팁:
- 너무 깊은 계층 피하기
- 정적 엔티티는 플래그로 표시하여 캐시 효율성 증대
- 여러 개의 루트 레벨 트랜스폼으로 분산
3.3 JobEntity를 사용한 대량 처리
Section titled “3.3 JobEntity를 사용한 대량 처리”using Unity.Entities;using Unity.Transforms;using Unity.Burst;
[BurstCompile]public partial struct MoveSystem : ISystem{ [BurstCompile] public void OnUpdate(ref SystemState state) { new MoveJob().ScheduleParallel(); }
[BurstCompile] private partial struct MoveJob : IJobEntity { public void Execute(ref LocalTransform transform) { // 모든 LocalTransform 컴포넌트를 병렬로 처리 transform.Position.y += 1.0f; } }}4. GameObject에서 ECS로의 마이그레이션 가이드
Section titled “4. GameObject에서 ECS로의 마이그레이션 가이드”4.1 단계별 마이그레이션 전략
Section titled “4.1 단계별 마이그레이션 전략”Phase 1: 분석 및 계획
- 기존 MonoBehaviour의 역할 분석
- ECS 컴포넌트 구조 설계
- 성능 이득이 큰 부분 우선 선정
Phase 2: 하이브리드 모드 도입
- ECS 패키지 설치
- 핵심 로직부터 ECS 시스템으로 재작성
- GameObject와 ECS 엔티티 간 상호작용 구현
Phase 3: 점진적 전환
- 한 번에 하나의 기능 단위로 전환
- 각 단계마다 테스트
- 성능 프로파일링으로 이득 확인
Phase 4: 완전 ECS 전환
- 모든 핵심 로직을 ECS 기반으로 구현
- GameObject 의존성 제거
- 성능 최적화
4.2 일반적인 마이그레이션 패턴
Section titled “4.2 일반적인 마이그레이션 패턴”MonoBehaviour 로직 → ECS
// Before: MonoBehaviour 기반public class EnemyController : MonoBehaviour{ private float speed = 5f;
void Update() { transform.position += Vector3.forward * speed * Time.deltaTime; }}
// After: ECS 기반public struct EnemySpeed : IComponentData{ public float Value;}
[BurstCompile]public partial struct EnemyMovementSystem : ISystem{ [BurstCompile] public void OnUpdate(ref SystemState state) { float deltaTime = SystemAPI.Time.DeltaTime;
foreach (var (transform, speed) in SystemAPI.Query<RefRW<LocalTransform>, RefRO<EnemySpeed>>()) { transform.ValueRW.Position += new float3(0, 0, 1) * speed.ValueRO.Value * deltaTime; } }}5. 실전 예제: 플레이어와 적 시스템
Section titled “5. 실전 예제: 플레이어와 적 시스템”5.1 컴포넌트 정의
Section titled “5.1 컴포넌트 정의”using Unity.Entities;using Unity.Mathematics;
// 플레이어 태그public struct Player : IComponentData {}
// 적 태그public struct Enemy : IComponentData {}
// 속도 데이터public struct Velocity : IComponentData{ public float3 Value;}
// 체력 데이터public struct Health : IComponentData{ public int CurrentHP; public int MaxHP;}
// 공격력 데이터public struct Damage : IComponentData{ public float Value;}5.2 움직임 시스템
Section titled “5.2 움직임 시스템”using Unity.Burst;using Unity.Entities;using Unity.Transforms;
[BurstCompile][UpdateInGroup(typeof(SimulationSystemGroup))]public partial struct MovementSystem : ISystem{ [BurstCompile] public void OnUpdate(ref SystemState state) { float deltaTime = SystemAPI.Time.DeltaTime;
new MovementJob { DeltaTime = deltaTime } .ScheduleParallel(); }
[BurstCompile] private partial struct MovementJob : IJobEntity { public float DeltaTime;
private void Execute(ref LocalTransform transform, in Velocity velocity) { transform.Position += velocity.Value * DeltaTime; } }}5.3 체력 시스템
Section titled “5.3 체력 시스템”using Unity.Burst;using Unity.Entities;
[BurstCompile]public partial struct HealthSystem : ISystem{ private EntityQuery destroyQuery;
[BurstCompile] public void OnUpdate(ref SystemState state) { var ecb = new EntityCommandBuffer(Allocator.Temp);
foreach (var (health, entity) in SystemAPI.Query<RefRW<Health>>().WithEntityAccess()) { if (health.ValueRO.CurrentHP <= 0) { ecb.DestroyEntity(entity); } }
ecb.Playback(state.EntityManager); }}6. 성능 최적화 팁
Section titled “6. 성능 최적화 팁”6.1 메모리 레이아웃 최적화
Section titled “6.1 메모리 레이아웃 최적화”- 컴포넌트 크기 최소화: 필요한 데이터만 저장
- 캐시 효율성: 자주 함께 접근하는 컴포넌트를 가까이 배치
- 정적 컴포넌트 표시:
IEnableableComponent로 활성/비활성 관리
6.2 시스템 순서 최적화
Section titled “6.2 시스템 순서 최적화”// 시스템 그룹을 활용한 실행 순서 제어[UpdateInGroup(typeof(SimulationSystemGroup))]public partial struct MySystem : ISystem { }6.3 Burst Compilation 활용
Section titled “6.3 Burst Compilation 활용”// [BurstCompile] 특성으로 성능 극대화[BurstCompile]public partial struct OptimizedSystem : ISystem{ // Burst로 컴파일되는 C# 코드 // C# Job System 사용 가능}7. 주의사항 및 일반적인 함정
Section titled “7. 주의사항 및 일반적인 함정”7.1 일반적인 실수
Section titled “7.1 일반적인 실수”- 변환 후 할당 누락:
transform.Position변경 후 할당 필수 - 부모 컴포넌트 누락: 계층 구조가 필요하면 반드시
Parent추가 - 시스템 실행 순서 문제: 의존성이 있는 시스템들은 올바른 순서로 실행되어야 함
- 메모리 누수: EntityCommandBuffer를 제때 해제하지 않으면 누수 발생
7.2 디버깅 팁
Section titled “7.2 디버깅 팁”// Entity 디버깅 출력Debug.Log($"Entity: {entity}");
// 컴포넌트 확인if (SystemAPI.HasComponent<Health>(entity)){ var health = SystemAPI.GetComponent<Health>(entity); Debug.Log($"Health: {health.CurrentHP}/{health.MaxHP}");}8. 공식 자료 및 커뮤니티
Section titled “8. 공식 자료 및 커뮤니티”8.1 공식 문서
Section titled “8.1 공식 문서”8.2 학습 자료
Section titled “8.2 학습 자료”- Unity Learn: “Basics of DOTS: Jobs and Entities”
- Entity Component System Samples (GitHub)
- HelloCube 튜토리얼
8.3 커뮤니티 지원
Section titled “8.3 커뮤니티 지원”- Unity Discussions - Entities 카테고리
- Official Unity Discord - DOTS 채널
Unity 6.4의 ECS 코어 패키지 통합으로 GameObject와 ECS를 함께 사용할 수 있게 되었습니다. 기존의 객체지향 게임 개발 방식에서 데이터 지향적 설계로 점진적으로 전환할 수 있으며, 이를 통해 성능, 확장성, 그리고 유지보수성을 크게 향상시킬 수 있습니다.
성능이 중요한 프로젝트라면 ECS 도입을 강력히 권장하며, 단계적 마이그레이션을 통해 리스크를 최소화할 수 있습니다.
- Unity Entity Component System: https://unity.com/ecs
- Entity Component System Documentation: https://docs.unity3d.com/Packages/com.unity.entities@latest
- ECS Concepts: https://docs.unity3d.com/Packages/com.unity.entities@0.1/manual/ecs_core.html
- Using Transforms in Entities: https://docs.unity3d.com/Packages/com.unity.entities@1.0/manual/transforms-using.html
- Kodeco ECS Tutorial: https://www.kodeco.com/7630142-entity-component-system-for-unity-getting-started
- DEV Community ECS Guide: https://dev.to/rk042/a-step-by-step-guide-to-creating-and-adding-components-in-unity-ecs-3f70