この記事でのバージョン
Unity 2022.2.8f1
はじめに
Unity公式のYoutubeチャンネルに新しいオブジェクト検索メソッドの動画が上がっていたので、
今回はこれを試してみようという感じの記事!
先に概要を列挙しておくと以下のような感じで、
- 旧メソッドのFindObject(s)OfTypeは無駄なソート処理をしていた
- 新メソッドはそれが無いので早いが、乱用出来る程ではない
- 旧メソッドはそのうち使えなくなる
今まで通り出来る限り使わない方が良いというのは変わらないのですが、
もし使う(使っている)場合は新メソッドを使いましょうという感じでした。
なお、対応しているUnityは以下のージョン以降になります。
2020.3.4, 2021.3.18, 2022.2.5, 2022.3 LTS.
高速化された新しいオブジェクト検索メソッド
そもそもオブジェクトを検索するメソッドはFindObjectsOfType
という物があって、これは遅い処理の代名詞でした。
//シーン内のBoxColliderを全て取得 var colliders = FindObjectsOfType<BoxCollider>(); Debug.Log($"BoxColliderの数{colliders.Length}");
それと同様の機能を早く実行出来るのが新メソッドのFindObjectsByTypeです。(ofがbyになった)
使い方は引数が増えただけで旧メソッドと同じです。
//シーン内のBoxColliderを全て取得 var colliders = FindObjectsByType<BoxCollider>(FindObjectsSortMode.None); Debug.Log($"BoxColliderの数{colliders.Length}");
試しに自分の環境で全BoxoColliderを取得する処理の時間を比較をしてみた所、
明らかに新メソッドの方が処理が早くなっていました。(処理時間の計測はProcessTimerを使用)
とは言え、何百倍早くなったとかではないので今まで通り多用は禁物です。
ちなみに何が変わったのかというと
旧メソッドは取得後にインスタンスIDでソートしていたのに対し、
新メソッドはそのソートが無くなっています。
(引数をFindObjectsSortMode.InstanceIDにすれば同じようにソート出来るが、当然重くなる)
なので、新メソッドは同じオブジェクトでも取得の順序が変わってくる事があります。
Debug.Log($"Of : {string.Join(", ", FindObjectsOfType<BoxCollider>().Select(collider => collider.gameObject.name))}"); Debug.Log($"By : {string.Join(", ", FindObjectsByType<BoxCollider>(FindObjectsSortMode.None).Select(collider => collider.gameObject.name))}");
なお、今後旧メソッドを使用すると警告が出るようになり、
いずれは使えなくなるので、新メソッドの方を使っていくようにしましょう。
ちなみに単体で取得するFindObjectOfTypeもインスタンスIDが小さい物を取得するという仕様があり、
それを無くして高速化した新メソッドFindAnyObjectByTypeがあります。
(旧メソッドと同じ仕様の新メソッドはFindFirstObjectByType)