Unity ECS(Enity Component System)로 눈의 결정 내리기

개시하다


Unite Tokyo 2018에는 ECS에 관한 강연이 있습니다.
  • [Unite 2018 Tokyo] C#Job System과 ECS(Enity Component System) 해설 - SlideShare
  • 이 가운데 ECS를 사용해 많은 눈이 내리는 시위 행진이 벌어졌기 때문에 이번에도 나 스스로 실행에 도전했다.

    ECS는 지금까지의 게임Object & Monobehavior와는 다른 데이터 지향형의 방법이다.
    ECS란 무엇입니까?이런 해설은 이곳의 보도를 배울 수 있다.
  • [Unity] Unity 2018의 Enity Component System(통칭 ECS)(1) - 테일러셔 블로그
  • 차리다


    ECS를 사용하기 위한 준비입니다.

    Unity 준비


    Unity2018.설치
    (이번에는 Unity 2018.1.0f2를 통해 검증)

    ECS 설치


    다음 항목은 Assets와 같은 층에 Packages라는 폴더가 있는데 그 중 manfest가 있습니다.제이슨을 다시 쓰다.
    manifest.json
    manifest.json
    {
        "dependencies":{
                "com.unity.incrementalcompiler": "0.0.38", 
            "com.unity.entities": "0.0.12-preview.1"
        },
        "testables": [
            "com.unity.collections",
            "com.unity.entities",
            "com.unity.jobs"
        ],
        "registry": "https://staging-packages.unity.com"
    }
    
    ECS와는 상관이 없지만 이 Pacages Manager의 구조를 넣어 Experimental과 베타 등을 가져오는 시험 기능이 상당히 수월해졌다.

    .NET 클래스


    Player Settings에서 온 것도 있습니다.NET 버전을 보십시오.x로 주세요.

    눈의 결정 모형


    이번에 우리는 Asset에 포함된 눈의 결정을 사용했다.
  • FREE Christmas Assets / Low Poly - Asset Store
  • 이루어지다


    다음 두 개의 스크립트를 준비합니다.
    SnowScrap.cs
    SnowScrap.cs
    using Unity.Entities;
    using Unity.Mathematics;
    using Unity.Rendering;
    using Unity.Transforms;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class SnowStrap : MonoBehaviour 
    {
        public Mesh snowMesh;
        public Material snowMaterial;
        public Text countText;
        public Text fpsText;
    
        public int step = 10; // 1フレームあたりに作る数
    
        // FPS
        private float m_updateInterval = 0.5f;
        private float m_accum;
        private int m_frames;
        private float m_timeleft;
        private float m_fps;
    
        // 雪結晶の数
        private int count = 0;
    
        private EntityManager entityManager;
        private EntityArchetype snowArchetype;
    
        // ECSで雪の結晶を作るエントリーポイント
        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
        private void Start()
        {
            entityManager = World.Active.GetOrCreateManager<EntityManager>();
    
            snowArchetype = entityManager.CreateArchetype(
                typeof(TransformMatrix),
                typeof(Position),
                typeof(Rotation),
                typeof(MeshInstanceRenderer)
            );
        }
    
        private void Update()
        {
            if (Input.GetKey(KeyCode.Space))
            {
                for (int i = 0; i < step; i++)
                {
                    var snow = entityManager.CreateEntity(snowArchetype);
    
                    entityManager.SetSharedComponentData(snow, new MeshInstanceRenderer
                    {
                        mesh = snowMesh,
                        material = snowMaterial,
                    });
    
                    entityManager.SetComponentData(snow, new Position
                    {
                        Value = new float3(Random.Range(-20.0f, 20.0f), 20, Random.Range(-20.0f, 20.0f))
                    });
                    entityManager.SetComponentData(snow, new Rotation
                    {
                        Value = Quaternion.Euler(0f, Random.Range(0.0f, 180.0f), 90f)
                    });
    
                    count++;
    
                }
    
                countText.text = count.ToString();
    
                // FPS
                m_timeleft -= Time.deltaTime;
                m_accum += Time.timeScale / Time.deltaTime;
                m_frames++;
    
                if ( 0 < m_timeleft ) return;
    
                m_fps = m_accum / m_frames;
                m_timeleft = m_updateInterval;
                m_accum = 0;
                m_frames = 0;
    
                fpsText.text = "FPS: " + m_fps.ToString("f2");
            }
        }
    }
    
    SnowMovementSystem.cs
    SnowMovementSystem.cs
    using Unity.Entities;
    using Unity.Transforms;
    
    public class SnowMovementSystem : ComponentSystem {
    
        // 落下速度
        private float delta = 0.1f;
    
        public struct SnowGroup
        {
            public ComponentDataArray<Position> snowPostion;
            public int Length;
        }
    
        [Inject] private SnowGroup _snowGroup;
    
        protected override void OnUpdate()
        {
            for (int i = 0; i < _snowGroup.Length; i++)
            {
                var newPos = _snowGroup.snowPostion[i];
                newPos.Value.y -= delta;
                _snowGroup.snowPostion[i] = newPos;
            }
        }
    }
    
    
    원래 눈의 결정을 보여주는 시스템과 눈을 움직이는 결정을 만드는 시스템의 2개 시스템이 필요한데, 렌더링과 관련된 시스템이 유닛 측에서 준비한 메시 인스턴트 렌더링 시스템이 있어 그걸 사용하고 있다.
    ComponetData도 Position 등 Unity 쪽에서 미리 준비해 두었기 때문에 스스로 하지 않았다.

    빈 게임 대상을 만듭니다.cs를 어셈블리로 붙여넣습니다.
    공공 필드 속성을 지정합니다.
    여기서 반드시 주의해야 할 것은 Material의 설정이다.

    EnableGPU Instancing을 확인해야 합니다.
    MeshInstance RenderSystem 내부에서 GPU Instancing을 사용하는 것 같습니다.
    최종 확인.
    Editor의 Run 버튼을 눌러 장면을 시작합니다.
    Unity->Window->EnityDebugger를 엽니다.
    ECS의 Enity는 등급표에 표시되지 않기 때문에 이쪽으로 확인하세요.

    Snow Movent System과 Mesh Instance Render System이 있다는 것을 알고 있습니다.
    시스템을 어떻게 운영하는지에 필요한 ComponetData와 Enity에 대한 자세한 정보(transform 등)를 확인할 수 있다.

    샘플 항목


    샘플 항목이 이미 Giithub로 올라갔다.
  • https://github.com/yuri-hattori/EcsSnowProject
  • 총결산


    ECS 신난다, 대단해!
    이렇게 간단한 것이라면 시스템과 데이터 구성 요소의 디자인에도 큰 망설임이 없을 것이다. 그러나 좀 더 큰 일을 하려면 디자인의 난이도가 높아지고 습관이 필요하다.
    우리도 렌더링처럼 유닛에서 준비한 시스템이 충실해지기를 기대하고 있다.

    참고 자료


    영어의 블로그 보도지만 매우 유용하다.
  • Unity - ECS Tutorial (Entity Component System) ( Blog + Video ) | WDTutorials
  • 이것은 정통 ECS 샘플이다.이것도 참고할 수 있다.
  • https://github.com/Unity-Technologies/EntityComponentSystemSamples
  • FPS 구매 방법은 여기를 참고했습니다.
  • [Unity] ECS를 이용하여 10000개의 사이다 샘플을 그린'ecs-istanced-sprite-render'소개-코네 블로그
  • 좋은 웹페이지 즐겨찾기