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では高速になるよう
考え方自体が変わるので移行は簡単には決められませんが
覚えておく必要はありそう