2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Unity]FindOfjectsOfType<T> と SceneのRootGameObjectsに対してGetComponents<T>するのではどちらが早いのか?

Posted at

結果 

rootからさらった方が早い

Editor

メソッド 平均処理時間(ms)
FindObjectOfType 10.0
FindObjectsOfType 11 .0
RootGameObject 3.5
RootGameObject(Listに追加) 3.0

findobject vs rootgameobject editor.JPG

standaloneでdevelopmentbuild + Autoconnect profiler

メソッド 平均処理時間(ms)
FindObjectOfType 6.5
FindObjectsOfType 6.9
RootGameObject 2.7
RootGameObject(Listに追加) 2.7

findobject vs rootgameobject mono.JPG

大雑把な環境

windows7
Unity 2018.4.5f1
.net 4.x
.net standard 2.0
mono

計測コード

profile.cs
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
public class NewBehaviourScript : MonoBehaviour
{
	const string ROOT_GAMEOBJECT_NO_BUFFERED = "rootGameObjects no buffered";
	const string ROOT_GAMEOBJECT_BUFFERED = "root game object buffered";
	const string FIND_OBJECTS_TYPE = "find object's of type";
	const string FIND_OBJECT_TYPE = "find object of type";

	// Start is called before the first frame update
	void Start()
	{
		for (int i = 0; i < 1000; i++)
		{
			var go = new GameObject($"number {i}");
			for (int y = 0; y < 20; y++)
			{
				go.AddComponent<Type1>();
				go.AddComponent<Type2>();
			}
		}
	}

	private List<Type1> _Type1s = new List<Type1>();
	private List<GameObject> GameObjects = new List<GameObject>();
	private List<Type1> _Type1sBuffer = new List<Type1>();
	// Update is called once per frame
	void Update()
	{
		GC.Collect();
		{
			Profiler.BeginSample(ROOT_GAMEOBJECT_NO_BUFFERED);
			var rootGameObjects = gameObject.scene.GetRootGameObjects();
			Type1[][] type1s = new Type1[rootGameObjects.Length][];
			for (int i = 0; i < rootGameObjects.Length; i++)
			{
				type1s[i] = rootGameObjects[i].GetComponentsInChildren<Type1>();
			}
			Profiler.EndSample();
		}
		GC.Collect();
		{
			Profiler.BeginSample(ROOT_GAMEOBJECT_BUFFERED);
			gameObject.scene.GetRootGameObjects(GameObjects);
			for (int i = 0; i < GameObjects.Count; i++)
			{
				GameObjects[i].GetComponentsInChildren(_Type1sBuffer);
				_Type1s.AddRange(_Type1sBuffer);
			}
			Profiler.EndSample();
			_Type1sBuffer.Clear();
			_Type1s.Clear();
			GameObjects.Clear();
		}
		GC.Collect();
		{
			Profiler.BeginSample(FIND_OBJECTS_TYPE);
			var type1s = GameObject.FindObjectsOfType<Type1>();
			Profiler.EndSample();
		}
		GC.Collect();
		{
			Profiler.BeginSample(FIND_OBJECT_TYPE);
			var type1 = GameObject.FindObjectOfType<Type1>();
			Profiler.EndSample();
		}
	}
}

//別ファイルで定義
public class Type1 : MonoBehaviour
{
}
public class Type2 : MonoBehaviour
{
}

感想

最初typoで単体のコンポーネントを拾ってくるFindObjectOfType()をつかってて
それですらRootのGameObjectを全部さらってGetComponentsInChildren()したやつより遅かったので
両方計測した結果FindObjectOfType()とFindObjectsOfType()が速度的に大差ないという驚きの結果を偶然得ることができました
FindObjectsOfType()を処理した結果の先頭を返してるっぽい挙動

重いと言うのは知ってましたが
単体の方ですら初期化でも使うのを躊躇うほどの処理負荷がかかるとは思ってませんでした

SceneからGameObject全部とってきてGetComponentsする方が一見すると重そうなのに
中でどういう実装が行われているのか知りませんが
似たような速度になるならともかく、どうしてこんなに差がでるほど遅いのか本当に謎ですね

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?