UnityのDOTSが1.0になったのでInstantiate速度比較


UnityのDOTSが半年ほど前に1.0になったようなので
GameObjectとEntityのInstantiate速度比較を行いました

Updateは?

MonoBehaviourのコールバックはC#通常の呼び出しより
コストがかかるという話に見えるのでUpdateは
自前マネージャを書くなりで対処を考えられますが
Instantiateは難しいのでそちらを優先して調査

こちらの方のLitMotionの記事が非常に参考になりました

テストコード

ECSのコードはたくさんの方が書かれているので
ここではキューブを作成するコード部分のみを
spawnCountはインスペクタからそれぞれ一万個設定

GameObject

public class GOSpawner : MonoBehaviour
{
    public GameObject prefab;
    public int spawnCount;

    void Start()
    {
        enabled = false;

        var watch = new Stopwatch();

        const float x_max = 100f;
        const float y_max = 100f;
        watch.Start();
        for(int i = 0; i < spawnCount; ++i)
        {
            var go = GameObject.Instantiate(prefab);

            var x = Random.Range(-x_max, x_max);
            var y = Random.Range(-y_max, y_max);
            go.transform.localPosition = new Vector3(x, y, 0f);
        }
        watch.Stop();

        UnityEngine.Debug.Log($"SPAWN_TIME:{watch.ElapsedMilliseconds}");
    }
}

Entity

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

    public void OnDestroy(ref SystemState state) {}

    public void OnUpdate(ref SystemState state)
    {
        state.Enabled = false;

        var watch = new Stopwatch();

        const float x_max = 100f;
        const float y_max = 100f;
        watch.Start();
        foreach(RefRW<Spawner> spawner in SystemAPI.Query<RefRW<Spawner>>())
        {
            for(int i = 0; i < spawner.ValueRO.spawnCount; ++i)
            {
                var newEntity = state.EntityManager.Instantiate(spawner.ValueRO.prefab);

                var x = UnityEngine.Random.Range(-x_max, x_max);
                var y = UnityEngine.Random.Range(-y_max, y_max);
                var spawnPosition = new Unity.Mathematics.float3(x, y, 0f);
                state.EntityManager.SetComponentData(newEntity, LocalTransform.FromPosition(spawnPosition));
            }
        }
        watch.Stop();

        UnityEngine.Debug.Log($"SPAWN_TIME:{watch.ElapsedMilliseconds}");
    }
}

結果

GameObjectのInstantiate
140-147ms

EntityのInstantiate
18-20ms

留意事項

Unityの通常通りの使い方だと親子関係があるが
この例ではSetParentなどは使っていない
あちらもコストが高い処理

雑感

Unityを使っているとInstantiateの速度問題も付いてくる
気がしていますが、素直にみるとDOTSでは高速になるよう
考え方自体が変わるので移行は簡単には決められませんが
覚えておく必要はありそう