Unity DOTS を使う

始めに

先日の UI Toolkit に続いて DOTS(Data-Oriented Technology Stack) も今後標準になっていくとの事。 であればどうやって使うのかを理解しておきたいという話。

参考

公式 PR https://unity.com/ja/dots

公式 ECS マニュアル https://docs.unity3d.com/Packages/com.unity.entities@1.0/manual/index.html

公式 Brust マニュアル https://docs.unity3d.com/Packages/com.unity.burst@1.8/manual/index.html

公式 Job System マニュアル https://docs.unity3d.com/2022.3/Documentation/Manual/JobSystem.html

公式 Learning DOTS https://github.com/Unity-Technologies/EntityComponentSystemSamples/#learning-dots

基礎知識

2D Support in DOTs? https://discussions.unity.com/t/2d-support-in-dots/900317

プロジェクトセットアップ

New Entities project setup https://github.com/Unity-Technologies/EntityComponentSystemSamples/blob/master/EntitiesSamples/Docs/project_setup.md

HDRP for mobile https://discussions.unity.com/t/hdrp-for-mobile/918839

Installing the Universal Render Pipeline into an existing Project https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@17.0/manual/InstallURPIntoAProject.html

お試し実装

using UnityEngine;
using Unity.Entities;

public class MainExecuteScript : MonoBehaviour
{
    class Baker : Baker<MainExecuteScript>
    {
        public override void Bake(MainExecuteScript mainExecuteScript)
        {
            var entity = GetEntity(TransformUsageFlags.None);
            AddComponent<ComponentData>(entity);
        }
    }

    public struct ComponentData : IComponentData
    {
    }
}
using UnityEngine;
using Unity.Entities;
using Unity.Mathematics;

public class CubeScript : MonoBehaviour
{
    public float DegreesPerSecond = 360.0f;

    class Baker : Baker<CubeScript>
    {
        public override void Bake(CubeScript cubeScript)
        {
            var entity = GetEntity(TransformUsageFlags.Dynamic | TransformUsageFlags.NonUniformScale);
            AddComponent(entity, new ComponetData
            {
                RadiansPerSecond = math.radians(cubeScript.DegreesPerSecond)
            });
        }
    }

    public struct ComponetData : IComponentData
    {
        public float RadiansPerSecond;
    }
}
using Unity.Burst;
using Unity.Entities;
using Unity.Transforms;

namespace Assets.Scenes
{
    public partial struct MainSystem : ISystem
    {
        [BurstCompile]
        public void OnCreate(ref SystemState state)
        {
            state.RequireForUpdate<MainExecuteScript.ComponentData>();
        }

        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            float deltaTime = SystemAPI.Time.DeltaTime;

            foreach (var (transform, speed) in
                     SystemAPI.Query<RefRW<LocalTransform>, RefRO<CubeScript.ComponetData>>())
            {
                transform.ValueRW = transform.ValueRO.RotateY(
                    speed.ValueRO.RadiansPerSecond * deltaTime);
            }
        }
    }
}

メモ

(2023/11/18 更新)

Method ShouldRunSystem https://docs.unity3d.com/Packages/com.unity.entities@1.0/api/Unity.Entities.ComponentSystemBase.ShouldRunSystem.html

TransformUsageFlags https://docs.unity3d.com/Packages/com.unity.entities@1.0/api/Unity.Entities.TransformUsageFlags.html

最後に感想など

ECS と Brust は触れたが、Job System やグラフィック関連は今後としておく。

2D サポートがないと知った際は正直言って萎えたが、 内容を見る限り部分的には使えそう。

後は、パフォーマンスは確かに大事だが、仕組みが過剰ではないかと思った。 ゲームを設計する時点で多数のオブジェクトがあるというなら良いが、 パフォーマンスが悪いからと後から導入するのは困難。 逆に導入したはいいがオブジェクトが減って苦労が無駄になるかも。

冒頭にも書いたが標準になっていくらしい。 しかしスクリプトを沢山作る必要がある点で、このままだと無理だと思った。

top