Unity DOTS/Dots Custom Manual

EntityPrefabReference 에 대해 알아보자

개양반 2024. 5. 3.
728x90

DOTS v1.2.1

EntityPrefabReference란?

Prefab을 런타임 중에 Entity 로 생성할 때 사용하는 구조체이다.

 

DOTS에서 Prefab을 Entity로 생성하는 방법

DOTS에서 Prefab을 Entity로 생성하는 방법에는 복제와 참조 두 가지 방식이 있다.  

보통은 복제하는 방식을 사용하지만, 게임의 규모가 큰 게임의 경우 여러 SubScene이 존재하는 경우는 참조하는 방식을 사용한다. 왜냐하면 복제의 경우 SubScene에서 이미 Baking 된 Prefab을 다른 SubScene에서 사용하려면 또 베이킹을 해야하기 때문이다. 참조의 경우는 하나의 SubScene에서 Baking을 했다면 참조를 통해 다른 SubScene에서도 Baking없이 Entity로 생성할 수 있다. 

 

1. 복제하는 방법

베이킹으로 MonoBehaviour에 멤버변수로 등록된 Prefab을 Entity로 만드는 방법이다. 

■ 코드 예제

using Unity.Collections;
using Unity.Entities;
using UnityEngine;


namespace PrefabReference
{

public class GetPrefabAuthoring : MonoBehaviour
{
    public GameObject Prefab;

    class Baker : Baker<GetPrefabAuthoring>
    {
        public override void Bake(GetPrefabAuthoring authoring)
        {
            // 프리팹을 등록하고 
            var entityPrefab = GetEntity(authoring.Prefab, TransformUsageFlags.Dynamic);

            // 스포너에 EntityPrefabComponent 추가
            var entity = GetEntity(TransformUsageFlags.None);
            AddComponent(entity, new EntityPrefabComponent(){
                Value = entityPrefab
            });

        }
    }
}

public struct EntityPrefabComponent : IComponentData
{
    public Entity Value;
}

public partial struct InstantiatePrefabSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        var ecb = new EntityCommandBuffer(Allocator.Temp);

        foreach (var prefab in
                 SystemAPI.Query<RefRO<EntityPrefabComponent>>())
        {
            // Entity 생성.
            ecb.Instantiate(prefab.ValueRO.Value);
        }

        ecb.Playback(state.EntityManager);
        ecb.Dispose();
    }
}

}

 

2. 참조하는 방법

베이킹할 때 EntityPrefabReference를 통해 Entity를 참조시킨다. 

System에서 참조시킨 Entity를 생성할 때 조금 복잡한 절차가 필요하다. 

1. RequestEntityPrefabLoaded 컴포넌트를 추가한다. 

2. RequestEntityPrefabLoaded 가 추가되면 프리팹 로드가 요청된다. 

3. 로드가 완료되면 Entity에게 PrefabLoadResult 컴포넌트가 추가된다. 

4. prefabLoadResult.PrefabRoot 를 통해 Entity를 인스턴스화(생성) 한다. 

 

■ 코드 예제

using Unity.Collections;
using Unity.Entities;
using Unity.Entities.Serialization;
using Unity.Scenes;
using UnityEngine;

namespace PrefabReference
{
public struct EntityPrefabReferenceComponent : IComponentData
{
    public EntityPrefabReference Value;
}

public class GetPrefabReferenceAuthoring : MonoBehaviour
{
    public GameObject Prefab;

    class Baker : Baker<GetPrefabReferenceAuthoring>
    {
        public override void Bake(GetPrefabReferenceAuthoring authoring)
        {
            // Prefab의 래퍼런스를 만든다. 
            var entityPrefab = new EntityPrefabReference(authoring.Prefab);

            // 스포너에 EntityPrefabReferenceComponent 추가
            var entity = GetEntity(TransformUsageFlags.Dynamic);
            AddComponent(entity, new EntityPrefabReferenceComponent() {Value = entityPrefab});
        }
    }
}

public partial struct InstantiatePrefabReferenceSystem : ISystem
{
    public void OnStartRunning(ref SystemState state)
    {
        var query = SystemAPI.QueryBuilder()
            .WithAll<EntityPrefabReferenceComponent>()
            .WithNone<PrefabLoadResult>().Build();
        
        // query로 조회된 Entity들에게 RequestEntityPrefabLoaded를 추가한다.
        // RequestEntityPrefabLoaded가 추가된 Entity는 Load를 시작한다.
        state.EntityManager.AddComponent<RequestEntityPrefabLoaded>(query);
    }

    public void OnUpdate(ref SystemState state)
    {
        var ecb = new EntityCommandBuffer(Allocator.Temp);

        // RequestEntityPrefabLoaded로 인하여 로드가 완료된 Entity에게는
        // PrefabLoadResult 가 추가된다.
        foreach (var (prefab, entity) in
                 SystemAPI.Query<RefRO<PrefabLoadResult>>().WithEntityAccess())
        {
            var instance = ecb.Instantiate(prefab.ValueRO.PrefabRoot);

            // Entity 생성에만 필요한 두개의 컴포넌트를 삭제한다. 
            ecb.RemoveComponent<RequestEntityPrefabLoaded>(entity);
            ecb.RemoveComponent<PrefabLoadResult>(entity);
        }

        ecb.Playback(state.EntityManager);
        ecb.Dispose();
    }
}
}

 

 

댓글

💲 추천 글