ECS – Component concepts (1)

1. Component란?

https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/concepts-components.html

Unity의 DOTS (Data-Oriented Technology Stack)에서 ECS(Entity Component System)의 핵심 요소 중 하나

ComponentData는 ECS에서 “데이터” 저장하는 구조체

https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/concepts-components.html

위의 예시에서 Speed, Direction, Position, RendererComponent

특징

  • 일반적으로 값 타입(struct) 선언
  • OOP의 클래스 필드와 비슷한 역할을 하지만, GameObjectMonoBehaviour 대신 Entity에 데이터를 부착하는 방식
  • Unity의 ECS는 데이터와 로직을 분리하여 성능을 극대화하는 구조이므로, IComponentData순수 데이터만 포함하는 것이 좋음

사용 예시

  • Entity의 위치를 저장하는 PositionComponent를 선언
using Unity.Entities;
using Unity.Mathematics;

// 위치 정보를 저장하는 컴포넌트
public struct PositionComponent : IComponentData
{
    public float3 Value;
}

2. IComponentData를 사용하여 Entity에 데이터 추가

IComponentData를 사용하려면 엔터티(Entity)에 추가해야 함

사용 예시

  • MonoBehaviour에서 ECS Entity로 데이터를 변환하는 Baker를 사용하여 PositionComponent를 Entity에 추가
using Unity.Entities;
using UnityEngine;

public class PositionAuthoring : MonoBehaviour
{
    public Vector3 Position;

    // Baker 클래스는 이를 ECS의 PositionComponent로 변환하여 엔터티에 추가
    class Baker : Baker<PositionAuthoring>
    {
        public override void Bake(PositionAuthoring authoring)
        {
            var entity = GetEntity(TransformUsageFlags.Dynamic);
            AddComponent(entity, new PositionComponent { Value = authoring.Position });
        }
    }
}

3. IComponentData를 읽고 수정하는 방법

ECS에서는 시스템(System)을 이용하여 데이터를 처리

사용 예시

  • IComponentDataComponentLookup<T> 또는 SystemAPI를 사용해 접근
  • Entities.ForEach 또는 IJobEntity를 사용해 병렬 처리
using Unity.Burst;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;

// BurstCompile을 사용하여 성능 최적화
[BurstCompile]
public partial struct MoveSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        // SystemAPI.Query<RefRW<T>>()를 사용하여 컴포넌트에 접근하고 데이터를 수정함
        foreach (var position in SystemAPI.Query<RefRW<PositionComponent>>())
        {
            position.ValueRW.Value += new float3(1, 0, 0); // X 방향으로 이동
        }
    }
}

4. 여러 종류의 Component

Component는 여러 다른 유형이 있음

프로젝트에서 데이터를 관리하는 방법에 따라 특정 Component를 사용하면 애플리케이션 성능을 보다 세밀하게 제어할 수 있음

ComponentDescription
Unmanaged components가장 일반적인 컴포넌트 유형이지만, 특정 유형의 필드만 저장할 수 있음
(struct 기반의 값 타입(Value Type) 만 저장 가능)
Managed components모든 유형의 필드를 저장할 수 있는 관리형(Managed) 컴포넌트
(가비지 컬렉션(GC) 영향을 받을 수 있어 성능에 주의)
Shared componentsEntity컴포넌트 값에 따라 Chunk단위로 그룹화
동일한 값을 가지는 엔터티들이 같은 메모리 Chunk에 저장되어 쿼리 성능을 향상
Cleanup componentsEntity가 파괴될 때 정리(Cleanup)가 필요한 경우 유용
Entity가 삭제될 때 Cleanup 컴포넌트를 제외한 모든 컴포넌트가 제거
Tag components데이터를 저장하지 않으며 메모리를 차지하지 않는 특수한 컴포넌트
Entity 쿼리에서 필터링할 때 유용. (IComponentData를 빈 struct으로 선언)
Buffer components (Dynamic buffer components)가변 크기 배열(Resizable Array) 역할을 하는 컴포넌트
예를 들어, 경로 점(Path Points) 목록이나 충돌 이벤트 리스트 등을 저장하는 데 사용됨
Chunk componentsEntity가 아니라 Chunk 전체에 값을 저장하는 컴포넌트
같은 Chunk에 속한 모든 엔터티가 동일한 값을 공유
Enableable components런타임 중에 활성화/비활성화할 수 있는 컴포넌트
구조적 변경(Structural Change) 없이 상태를 변경할 수 있어 성능 비용을 절약 가능.
Singleton components월드(World) 내에서 단 하나의 인스턴스만 존재하는 컴포넌트
전역 상태 저장용으로 자주 사용됨

Editor에서 Component types

에디터에서 다음 아이콘은 다양한 컴포넌트 유형을 나타냅니다. 이는 관련 Entities windows and Inspectors에 나타납니다.

IconComponent type
A managed component.
A shared component.
A tag component.
A buffer component.
A chunk component.

Unity는 목록에 없는 구성 요소 유형에 대해 일반적인 구성 요소 아이콘을 사용합니다.

(1) Unmanaged components

https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/components-unmanaged.html

Unmanaged components는 일반적인 데이터 유형을 저장하는 데 사용하며 아래 유형의 필드를 저장할 수 있음

  • Blittable types
  • bool
    true 또는 false 값을 가지는 논리형(Boolean) 타입
  • char
    단일 문자(Character)를 저장, 일반적으로 UTF-16 코드 단위
  • BlobAssetReference<T> 
    Blob 데이터 구조에 대한 참조, 대량의 불변(Immmutable) 데이터를 효율적으로 저장하고 공유하는 데 사용
  • Collections.FixedString 
    고정 크기(Fixed-Size) 문자열 버퍼
    가변 크기 문자열인 string 대신 GC(가비지 컬렉션) 없이 문자열을 저장할 때 사용
  • Collections.FixedList
    고정 크기 리스트(Fixed-Size List), 일반 List<T> 대신, 할당 없이 고정된 크기의 배열을 사용하는 리스트 구조.
  • Fixed array (unsafe context에서만 사용 가능)
  • 기타 Blittable 조건을 충족하는 구조체(Structs)
    Blittable 타입만 포함하는 다른 struct도 Blittable 타입이 될 수 있음
    즉, 모든 필드가 Blittable 타입으로 구성된 struct는 Blittable로 간주됨.

Blittable 타입

Blittable(블리터블)이란, 메모리에서 직접 복사(Copy)할 수 있는 데이터 타입을 의미

쉽게 말해, CPU가 메모리를 변환 없이 그대로 읽고 쓸 수 있는 데이터 타입

ECS(Entity Component System)에서 IComponentData는 Blittable 타입을 요구함

Blittable 타입은 관리되지 않는 네이티브 메모리에서 안전하게 사용할 수 있어 성능이 뛰어남

가비지 컬렉션(GC) 영향을 받지 않아 메모리 효율성이 높아짐

Blittable 타입CPU가 변환 없이 직접 복사 가능
bool, char, int, float, double✅ 기본적인 값 타입(Primitive Type)
float2, float3, float4 (Unity.Mathematics)✅ SIMD 연산 최적화 가능
BlobAssetReference<T>✅ Blob 데이터 구조체
FixedString, FixedList✅ 고정 크기의 문자열 및 리스트
Non-Blittable 타입❌ 직접 복사할 수 없고 변환이 필요함
string❌ 가변 길이 문자열 (Heap 할당)
List<T> / Dictionary<K, V>❌ 동적 크기 컨테이너 (Heap 할당)
class (참조 타입)❌ 힙 메모리에 저장되며, 포인터를 가짐
object❌ 박싱(Boxing) 필요
using Unity.Burst;
using Unity.Entities;
using Unity.Mathematics;

// Blittable한 IComponentData 구조체 정의
public struct MoveSpeed : IComponentData
{
    public float Value; // Blittable 타입(float) 사용
}

// 엔터티에 MoveSpeed 컴포넌트를 추가하는 Authoring 스크립트
using UnityEngine;

public class MoveSpeedAuthoring : MonoBehaviour
{
    public float speed;

    class Baker : Baker<MoveSpeedAuthoring>
    {
        public override void Bake(MoveSpeedAuthoring authoring)
        {
            var entity = GetEntity(TransformUsageFlags.Dynamic);
            AddComponent(entity, new MoveSpeed { Value = authoring.speed });
        }
    }
}

// MoveSpeed 값을 사용하여 Entity를 이동시키는 시스템
[BurstCompile] // 성능 최적화
public partial struct MoveSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        foreach (var moveSpeed in SystemAPI.Query<RefRW<MoveSpeed>>())
        {
            moveSpeed.ValueRW.Value += 0.1f; // X 방향으로 이동 속도 증가
        }
    }
}

(2) Managed Components

https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/components-managed.html

Managed Components(관리되는 컴포넌트)는 어떤 타입의 필드라도 저장할 수 있는 IComponentData이지만, 성능상 단점이 있음.

  • class 타입으로 선언하며, GC(가비지 컬렉션)의 영향을 받음
  • Job System과 Burst 컴파일러에서 사용 불가
  • 직렬화(Serialization)를 위해 매개변수가 없는 생성자 필수
특징Managed ComponentsUnmanaged Components
저장 가능한 데이터모든 타입 사용 가능Blittable 타입만 가능
메모리 저장 방식개별 배열(Array) 관리ECS의 Chunk에 직접 저장
Burst 지원❌ 지원되지 않음✅ 지원됨
Job System 사용 가능 여부❌ 불가능✅ 가능
GC 영향❌ GC 발생✅ GC 없음
직렬화 필요 여부✅ 매개변수 없는 생성자 필수❌ 필요 없음

Managed Component 생성 예시

using Unity.Entities;

// 클래스(class) 타입으로 Managed Component 생성
public class ExampleManagedComponent : IComponentData
{
    public int Value; // 관리되는 타입(int) 저장 가능
}

Managed Component를 Entity에 추가하는 Authoring 스크립트 예시

using UnityEngine;
using Unity.Entities;

public class ExampleManagedComponentAuthoring : MonoBehaviour
{
    public int Value;

    class Baker : Baker<ExampleManagedComponentAuthoring>
    {
        public override void Bake(ExampleManagedComponentAuthoring authoring)
        {
            var entity = GetEntity(TransformUsageFlags.Dynamic);
            AddComponent(entity, new ExampleManagedComponent { Value = authoring.Value });
        }
    }
}

Managed Component를 조회하고 수정하는 시스템 예시

using Unity.Entities;
using Unity.Burst;

// Managed Component는 Burst를 사용할 수 없음
// [BurstCompile] 사용 불가능
public partial struct ExampleManagedComponentSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        
        foreach (var managedComponent in SystemAPI.Query<ExampleManagedComponent>())
        {
            // 주의:Managed Component는 RefRW<T>로 접근할 수 없으며, 직접 접근 방식을 사용해야 함.
            managedComponent.Value += 1; // 값 증가
        }
    }
}

외부 리소스를 관리하는 Managed Component (ICloneable & IDisposable)

  • Managed Component가 외부(UnityEngine.Object) 리소스를 참조할 경우, 복제 및 제거 시 주의해야 함.
using UnityEngine;
using Unity.Entities;
using System;

// 외부 리소스의 수명 주기를 관리
public class ManagedComponentWithResource : IComponentData, IDisposable, ICloneable
{
    public ParticleSystem ParticleSystem; // Unity Object 참조

    // 엔터티가 삭제될 때 ParticleSystem도 파괴되도록 설정
    public void Dispose()
    {
        UnityEngine.Object.Destroy(ParticleSystem);
    }

    // 엔터티를 복제할 때 새로운 ParticleSystem을 생성하도록 설정
    public object Clone()
    {
        return new ManagedComponentWithResource
        {
            ParticleSystem = UnityEngine.Object.Instantiate(ParticleSystem)
        };
    }
}

Managed Component를 이용한 최적화

Managed Component는 성능이 낮기 때문에, 가능한 경우 Unmanaged Component를 사용해야

그러나, 아래와 같은 상황에서는 Managed Component를 사용할 수밖에 없음

  • Unmanaged Component로 표현할 수 없는 데이터 저장 (string, List<T>, class)
  • UnityEngine.Object를 직접 참조해야 하는 경우 (GameObject, ParticleSystem)
  • GC 부하를 감수하고라도 가변 데이터 구조 필요할 때

(3) Shared Components

https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/components-shared.html

Shared Components(공유 컴포넌트)는 같은 값을 가진 Entity들을 같은 Chunk로 그룹화하는 ISharedComponentData 타입

일반 IComponentData와 다르게, Chunk 단위로 저장되며, 동일한 값의 Entity들은 같은 Chunk에 배치됩니다.

항목Shared ComponentsUnmanaged Components
저장 단위Chunk 단위 저장개별 Entity별 저장
Burst 지원❌ 지원되지 않음✅ 지원됨
Job System 사용 가능 여부❌ 불가능✅ 가능
GC 영향❌ GC 발생 가능✅ GC 없음
직렬화 필요 여부✅ 필요함❌ 필요 없음
데이터 변경 시 영향값이 바뀌면 Chunk가 재배치됨구조적 변경 없음

Shared Components는 같은 값을 가진 Entity들이 같은 Chunk에 배치되므로 메모리 캐시 적중률을 높이는 데 유용

그러나, 값을 변경할 경우 Entity가 다른 Chunk로 이동해야 하므로 빈번한 변경이 필요할 경우 적합하지 않음

Managed Components와 달리, struct 타입으로 선언하지만 내부적으로 class를 포함할 수 있음

Burst 및 Job System을 사용할 수 없으므로 성능이 중요한 곳에서는 Unmanaged Components를 사용하는 것이 좋음

Shared Component 생성 예시

using Unity.Entities;

// ISharedComponentData를 상속받아 Shared Component 생성
public struct ExampleSharedComponent : ISharedComponentData
{
    public int GroupId; // 같은 GroupId를 가진 엔터티들은 같은 Chunk에 저장됨
}

Shared Component를 Entity에 추가하는 Authoring 스크립트

using UnityEngine;
using Unity.Entities;

public class ExampleSharedComponentAuthoring : MonoBehaviour
{
    public int groupId;

    class Baker : Baker<ExampleSharedComponentAuthoring>
    {
        public override void Bake(ExampleSharedComponentAuthoring authoring)
        {
            var entity = GetEntity(TransformUsageFlags.Dynamic);
            // AddComponent가 아닌 AddSharedComponent()를 사용해야 함
            // 같은 groupId 값을 가진 엔터티들이 같은 Chunk에 배치됨
            AddSharedComponent(entity, new ExampleSharedComponent { GroupId = authoring.groupId });
        }
    }
}

Shared Component를 조회하는 시스템

using Unity.Entities;
using Unity.Burst;

// Shared Component는 Burst를 사용할 수 없음
// [BurstCompile] 사용 불가능
public partial struct ExampleSharedComponentSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        foreach (var (sharedComponent, entity) in SystemAPI.Query<ExampleSharedComponent>().WithEntityAccess())
        {
            UnityEngine.Debug.Log($"Entity {entity.Index} has GroupId {sharedComponent.GroupId}");
        }
    }
}

Shared Component는 일반적인 IComponentData처럼 RefRW<T>로 접근할 수 없음

대신 직접 값 복사 방식으로 접근해야 함

WithEntityAccess()를 사용하면 어떤 엔터티가 해당 Shared Component를 가지고 있는지 확인 가능

Shared Component 값 변경

  • Shared Components는 값이 변경되면 새로운 Chunk가 생성되므로, 자주 변경되는 값에는 적합하지 않음.
public partial struct UpdateSharedComponentSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        foreach (var (entity, sharedComponent) in SystemAPI.Query<Entity, ExampleSharedComponent>())
        {
            if (sharedComponent.GroupId == 1)
            {
                state.EntityManager.SetSharedComponent(entity, new ExampleSharedComponent { GroupId = 2 });
            }
        }
    }
}

Shared Component를 활용하는 예제

  • 렌더링 레이어 그룹화
// Layer 값이 같은 엔터티들을 같은 Chunk에 배치
// 같은 레이어의 엔터티들을 한 번에 처리하여 렌더링 최적화 가능
public struct RenderLayer : ISharedComponentData
{
    public int Layer;
}
  • AI 행동 그룹화
// StateId 값이 같은 적(AI)들은 같은 Chunk에 배치됨
// 특정 AI 그룹을 한 번에 업데이트할 때 유용
public struct AIState : ISharedComponentData
{
    public int StateId;
}
  • 팀 구분
using Unity.Entities;

// 팀 정보를 저장하는 Shared Component
public struct TeamComponent : ISharedComponentData
{
    public int TeamId; // 같은 TeamId를 가진 Entity들은 같은 Chunk에 저장됨
}
using UnityEngine;
using Unity.Entities;

// 팀을 설정하는 Authoring
public class TeamComponentAuthoring : MonoBehaviour
{
    public int teamId;

    class Baker : Baker<TeamComponentAuthoring>
    {
        public override void Bake(TeamComponentAuthoring authoring)
        {
            var entity = GetEntity(TransformUsageFlags.Dynamic);
            AddSharedComponent(entity, new TeamComponent { TeamId = authoring.teamId });
        }
    }
}
using Unity.Entities;
using Unity.Burst;
using UnityEngine;

// Burst 사용 불가능 (Shared Component는 Job System에서 직접 접근 불가)
public partial struct TeamSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        foreach (var (teamComponent, entity) in SystemAPI.Query<TeamComponent>().WithEntityAccess())
        {   
            // WithEntityAccess()를 사용하면 특정 엔터티가 어느 팀에 속해 있는지 확인 가능
            Debug.Log($"Entity {entity.Index} belongs to Team {teamComponent.TeamId}");
        }
    }
}
public partial struct TeamFilterSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        // 특정 팀 ID(예: TeamId == 1)를 가진 엔터티들만 가져오기
        var query = SystemAPI.QueryBuilder().WithAll<TeamComponent>().Build();
        state.EntityManager.SetSharedComponent(query, new TeamComponent { TeamId = 1 });

        foreach (var (teamComponent, entity) in SystemAPI.Query<TeamComponent>().WithEntityAccess())
        {
            if (teamComponent.TeamId == 1)
            {
                Debug.Log($"Entity {entity.Index} is in Team 1");
            }
        }
    }
}

정리

  • 같은 값을 가진 Entity들을 같은 Chunk에 저장하여 메모리 접근 최적화 가능
  • 자주 변경되지 않는 데이터에 적합 (예: 렌더링 그룹, AI 상태, 네트워크 동기화 등)
  • 값이 변경될 경우 새로운 Chunk로 이동해야 하므로 변경이 잦다면 비효율적
  • Burst 및 Job System을 사용할 수 없으므로 성능이 중요한 경우 Unmanaged Component 사용이 더 적합

“자주 변경되지 않는” 데이터를 기준으로 Entity를 그룹화할 때 Shared Component를 사용

(4) Cleanup components

https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/components-cleanup.html

Cleanup Components는 일반 컴포넌트와 유사하지만, 특정 Entity가 삭제될 때 추가적인 정리 작업을 수행할 수 있도록 설계된 특수한 컴포넌트

이 컴포넌트는 Entity가 삭제될 때 모든 일반 컴포넌트를 제거하고, Entity 자체는 Cleanup Components가 모두 제거될 때까지 남아 있음

Entity가 삭제될 때 추가적인 정리 작업(예: 리소스 해제, 이벤트 처리 등)이 필요한 경우에 유용

  • ICleanupComponentData : 각 Entity별로 독립적인 정리 작업을 수행하며, 엔티티가 삭제될 때 개별적으로 동작
  • ICleanupSharedComponentData : 여러 Entity가 공유하는 데이터를 정리할 때 사용 (같은 리소스를 여러 Entity가 사용할 때, 리소스를 관리하고 정리하는 역할)
항목설명
목적엔티티가 삭제될 때 추가적인 정리 작업을 수행하기 위해 사용
동작 방식엔티티가 삭제될 때 모든 일반 컴포넌트를 제거하고, Cleanup Components만 남깁니다.
엔티티는 Cleanup Components가 모두 제거될 때까지 존재합니다.
사용 사례– 리소스 해제
– 이벤트 처리
– 네트워크 동기화 정리
– 엔티티 삭제 시 추가 로직 실행
Burst 지원✅ 지원됨
Job System 사용 가능 여부✅ 가능
GC 영향✅ GC 없음 (Unmanaged Components와 동일)
직렬화 필요 여부❌ 필요 없음

Cleanup Components의 동작 원리

  1. 엔티티 삭제 시 동작:
    • 엔티티가 삭제되면 모든 일반 컴포넌트가 제거
    • Cleanup Components는 남아 있으며, 엔티티는 여전히 존재
  2. Cleanup Components 제거:
    • Cleanup Components가 모두 제거되면 엔티티가 완전히 삭제
  3. 정리 작업 수행:
    • Cleanup Components를 사용하여 엔티티 삭제 시 필요한 추가 작업(예: 리소스 해제, 이벤트 처리 등)을 수행

Cleanup component 생명주기

// Cleanup 컴포넌트를 포함하는 엔티티를 생성합니다.
Entity e = EntityManager.CreateEntity(
    typeof(Translation), typeof(Rotation), typeof(ExampleCleanup));

// 엔티티를 삭제하려고 시도하지만, 엔티티가 Cleanup 컴포넌트를 가지고 있기 때문에 Unity는 실제로 엔티티를 삭제하지 않습니다.
// 대신, Unity는 Translation 및 Rotation 컴포넌트만 제거합니다.
EntityManager.DestroyEntity(e);

// 엔티티는 여전히 존재하므로, 엔티티를 정상적으로 사용할 수 있음을 보여줍니다.
EntityManager.AddComponent<Translation>(e);

// 엔티티에서 남아 있는 모든 컴포넌트를 제거합니다.
// 마지막 Cleanup 컴포넌트(ExampleCleanup)를 제거하면 엔티티가 자동으로 삭제됩니다.
EntityManager.RemoveComponent(e, new ComponentTypeSet(typeof(ExampleCleanup), typeof(Translation)));

// 엔티티가 더 이상 존재하지 않음을 보여줍니다. entityExists는 false입니다.
bool entityExists = EntityManager.Exists(e);
  • Cleanup Components 생성 예시
using Unity.Entities;

// ICleanupComponentData를 상속받아 Cleanup Component를 정의
// 엔티티가 삭제될 때 추가적인 정리 작업을 수행하는 데 사용
public struct CleanupComponent : ICleanupComponentData
{
    public int ResourceId; // 정리할 리소스 ID
}
  • Cleanup Components를 Entity에 추가하는 Authoring 스크립트
using UnityEngine;
using Unity.Entities;

public class CleanupComponentAuthoring : MonoBehaviour
{
    public int resourceId;

    class Baker : Baker<CleanupComponentAuthoring>
    {
        public override void Bake(CleanupComponentAuthoring authoring)
        {
            var entity = GetEntity(TransformUsageFlags.Dynamic);
            // AddComponent를 사용하여 Cleanup Component를 엔티티에 추가
            AddComponent(entity, new CleanupComponent { ResourceId = authoring.resourceId });
        }
    }
}

(5) Tag components

https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/components-tag.html

Tag components는 특별한 컴포넌트 유형으로, 주로 Entity를 분류하거나 특정 상태를 나타내는 데 사용

Tag components는 데이터를 저장하지 않고, 그 자체로 “표식” 역할

이는 예를 들어 Entity가 특정 범주에 속하는지, 아니면 특정 조건을 만족하는지를 나타내는 데 유용

Tag componentsEntity의 동작에 대한 부가적인 의미를 제공하기 위해 사용

이 컴포넌트는 상태를 나타내는 단순한 “플래그”로, 해당 컴포넌트가 존재하는지 여부만 확인하면 됩니다.

예를 들어, EnemyPlayer와 같은 태그 컴포넌트를 사용하여 Entity가 어떤 종류의 객체인지를 표시할 수 있습니다.

using Unity.Entities;

// Tag Component 정의 (데이터를 가지지 않음)
public struct PlayerTag : IComponentData { }

public struct EnemyTag : IComponentData { }
using Unity.Entities;
using Unity.Transforms;
using UnityEngine;

public struct TagComponentSearchSystem : ISystem
{
    public void OnCreate(ref SystemState state) { }

    public void OnDestroy(ref SystemState state) { }

    public void OnUpdate(ref SystemState state)
    {
        // PlayerTag를 가진 엔티티를 찾아서 처리
        var playerQuery = SystemAPI.QueryBuilder().WithAll<PlayerTag, Translation>().Build();

        foreach (var (playerTag, translation) in playerQuery)
        {
            // 플레이어 엔티티가 있을 때 처리할 코드
            Debug.Log("Player found at position: " + translation.Value);
        }

        // EnemyTag를 가진 엔티티를 찾아서 처리
        var enemyQuery = SystemAPI.QueryBuilder().WithAll<EnemyTag, Translation>().Build();

        foreach (var (enemyTag, translation) in enemyQuery)
        {
            // 적 엔티티가 있을 때 처리할 코드
            Debug.Log("Enemy found at position: " + translation.Value);
        }
    }
}
using Unity.Entities;
using Unity.Transforms;

public class TagComponentSearchSystem : SystemBase
{
    protected override void OnUpdate()
    {
        // PlayerTag를 가진 엔티티를 찾아서 처리
        Entities.ForEach((in PlayerTag playerTag, in Translation translation) =>
        {
            // 플레이어 엔티티가 있을 때 처리할 코드
            UnityEngine.Debug.Log("Player found at position: " + translation.Value);
        }).Run();

        // EnemyTag를 가진 엔티티를 찾아서 처리
        Entities.ForEach((in EnemyTag enemyTag, in Translation translation) =>
        {
            // 적 엔티티가 있을 때 처리할 코드
            UnityEngine.Debug.Log("Enemy found at position: " + translation.Value);
        }).Run();
    }
}

“ECS – Component concepts (1)”에 대한 2개의 생각

  1. 핑백: ECS – Component concepts (3) - 어제와 내일의 나 그 사이의 이야기

  2. 핑백: ECS – Component concepts (2) - 어제와 내일의 나 그 사이의 이야기

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤