Unity DOTS/ECS Sample Projtect

ECS Sample Project #4 SpawnFromMonoBehaviour

개양반 2022. 7. 29.
728x90

이전 글 보기

[Unity DOTS/ECS Sample Projtect] - ECS Sample Project #1 ForEach

[Unity DOTS/ECS Sample Projtect] - ECS Sample Project #2 IJobEntityBatch

[Unity DOTS/ECS Sample Projtect] - ECS Sample Project #3 Sub Scene


오늘 알아볼 내용

지금까지는 ConvertToEntity 옵션을 활성화한 GameObject가 Entity로 Convert 되도록 만들었지만 이번에는 GameObject가 Prefab GameObject를 Entity로 생성하는 방법에 대해 알아봅니다. 

개수는 많아졌지만 여전지 빙글빙글 돈다

 


새로운 씬을 만들고 이름을 4. SpawnFromMonoBehaviour 로 만들어 원하는 폴더에 저장합니다. Scripts 폴더에 4. SpawnFromMonoBehaviour를 만듭니다.

 


Spawner_FromMonoBehaviour 작성

Monobehavior 로 작성할 예정입니다. 4. SpawnFromMonoBehaviour폴더에 C# 파일을 만들고 이름을 Spawner_FromMonoBehaviour로 만듭니다. 아래의 코드를 작성합니다.

using UnityEngine;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;

public class SpawnFromMonoBehaviour : MonoBehaviour
{
    public GameObject Prefab;
    public int CountX = 100;
    public int CountY = 100;

    private void Start()
    {
        // 1. Settings 값 가져오기
        var settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, null);

        // 2. Prefab을 Entity 형태로 만들기
        var entity = GameObjectConversionUtility.ConvertGameObjectHierarchy(Prefab, settings);

        // 3. EntityManager 가져오기
        var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;

        for (int x = 0; x < CountX; x++)
        {
            for (int y = 0; y < CountY; y++)
            {
                var instance = entityManager.Instantiate(entity); // Entity 생성

                // instance의 Translation 값 변경
                var position = transform.TransformPoint(new float3(x * 1.3f, noise.cnoise(new float2(x, y) * 0.21f) * 2, y * 1.3f));
                entityManager.SetComponentData(instance, new Translation { Value = position});
            }
        }
    }
}

#코드 설명

GameObject에서 Entity를 만들고 생성하는 과정이다. 

 

1. GameObjectConversionSettings

GameObject를 Conversion할때 필요한 Settings 값이다. 여기서 DefaultGameObjectInjectionWorld에 속해있는 Setting 값을 가져오는 내용인데 지금까지 우리가 작업한 World가 DefaultWorld다. 우리가 DOTS 초고수가 되기 전까지는 DefaultWorld와 Physics 관련 월드 몇개만 사용할테니 깊게 파고 들어가지 않아도 될 거 같다. 

null 로 전달한 매개변수에는 여러 Entity에서 쉽게 접근해서 데이터를 참조하는 BlobAssetStore 라는 녀석을 전달하는데 여기서는 하나의 GameObject에서만 접근하므로 null 값을 전달했다. BlobAssetStore 에 대해서는 추후에 자세히 다룰 예정이다. 

 

2. GameObjectConversionUtility

위에서 만든 Settings를 가지고 GameObject를 Entity로 변환시키는 코드이다. 매개변수로 Prefab과 GameObjectConversionSettings를 전달한다. 

1~2 번 과정으로 Prefab을 Entity로 변환시켰다. 이건 그냥 외우면 된다. 복잡하게 깊게 알 필요가 없다. DOTS를 계속 공부하다보면 알아서 깊게 알게 된다. 

 

3. EntityManager가져오기

위에서 만든 Entity를 생성한 뒤에 Component 값을 변경하려면 메인스레드 에서만 동작하는 EntityManager가 필요하다. DefaultWorld에 속해있는 EntityManager를 가져온다. (우리가 초고수가 되기 전까지는 DefaultWorld와 Physics 관련 몇개의 월드만 사용하게 될테니 현재는 World에 대해 깊게 알 필요는 없을거같다. DOTS를 공부하다보면 World에 대해서도 자연스럽게 알게 된다.)

 

4. transform.TransformPoint

매개변수로 전달한 new float3를 Vector3 를 반환한다.

x * 1.3F, noise.cnoise(new float2(x, y) * 0.21F) * 2, y * 1.3F)는 지그재그로 배치하려고 사용한 코드이다. 중요한건 아니니 관심있는 분은 따로 noise.cnoise를 검색해서 알아보자. 

마지막으로 Entity의 속성 변경, 삭제, 추가 등은 EntityManager를 통해 이뤄진다. EntityManager는 메인스레드에서만 동작하며 멀티스레드에서는 CommandBuffer라는 놈을 이용한다. 추후에 설명할 예정이다.

 


테스트 환경 만들기

1. Spawner 게임오브젝트 만들기

Hierarchy뷰에서 빈게임오브젝트를 만들고 이름을 Spawner로 만든다. Spawner에 방금 만든 Spawner_FromMonoBehaviour.cs를 추가한다.

 

2. Cube 만들기

Cube를 두개 만들고 부모 자식 관계로 만든다. #1 ForEach에서 만든 RotationSpeed_ForEach를 Component로 추가한다. 

Cube를 Prefab으로 만들고 Hirarchy뷰에서 삭제한다. Cube Prefab을 Spawner의 SpawnFromMonoBehaviour의 Prefab변수에 연결한다.

 


테스트하기

Play 버튼을 누르면 수많은 Cube Entity가 빙글빙글 돌고 있을 것이다. DOTS Hierarchy 뷰에서 Entity들을 확인한다.

 

Spawner 게임오브젝트는 Entity로 변환시키지 않았기 때문에 DOTS Hierarchy뷰가 아닌 Hierarchy뷰에 존재한다.

댓글

💲 추천 글