開発どうもこんにちは、ちはるです。Unityには、GameObjectクラスを使ってScene中のオブジェクトのコンポーネントを取得する方法がいくつかあります。ついて今回はUnity*1で次のような環境を用意しました。Hierarchy内に、UI要素としてImageTextButtonを各10個ずつ配置(各要素が重なっているため、Game画面には1個ずつしか見えてない)しています。10個あるButtonのうち1個をTargetButtonとし、その中の子要素であるTextをTargetTextとしています。今回の検証では、このTargetTextのコンポーネントをあの手この手で取得していこうと思います。TargetButtonとTargetTextには、それぞれ以下のようにオブジェクト名と同じTagを付与してあります。検証する関数について使用関数1:GameObject#Find()まず、オブジェクトを取得する方法その1。これはGameObjectクラスのFind関数を使用して、対象オブジェクト(ここで言うTargetText)を取得し、そのオブジェクトからコンポーネントを取得してやるという方法です。}}この関数はアクティブなオブジェクト全てに対し、指定された名前に一致するものを総当たりで探します。上記のようなStartメソッド内でならまだしも、Updateメソッドなんかで使った日には......、恐ろしいですね。使用関数2:GameObject#FindWithTag()続いて検証する関数その2。この関数はFind関数と異なり、指定したTagが付与されたアクティブオブジェクトを取得します。}}Find関数と見た感じはかなり似ていますが、Tagを付与してやるだけで総当たり検索を回避できるようです。オブジェクト取得後のコンポーネント取得方法は方法1と同じです。使用関数3a:GameObject#GetComponentInChildren()つづいてがコチラ。このGetComponentInChildren関数は、深さ優先探索でゲームオブジェクトの子要素のコンポーネントを取得します。ここでは、子要素の探索を行う対象のゲームオブジェクト(親要素)を、方法1のFind関数にて取得します。}}使用関数3b:GameObject#GetComponentInChildren()こちらは、コンポーネントを取得する際に使用する関数はそのままで、親要素となるゲームオブジェクトの取得に、FindWithTag関数を用います。}}使用関数4:Transform#Find()最後に紹介する方法は、これまでとはチョット趣の違ったもの。いうのも、まず親要素を取得し、この親要素にアタッチされているTransformから、Transformの子要素を名前指定で取得するという方法です。}}ちなみに、ここで使用しているFind関数はGameObject#Find()とは別物なので、当然のことながらFindWithTag関数は使えません。検証方法について実際に利用するスクリプトこれまで列挙してきた手段を用い、TargetTextのコンポーネントを取得していきます。実際に実行するソースは以下のもの。}}こいつをMainCameraにアタッチしてやり、シーンを実行した際に処理が走るようにします。紹介した5パターンのコンポーネント取得処理を、10万回3セット行います。実際の時間計測にはStopWatchクラスを使用し、各セット毎に処理に要した時間をログ出力します。TargetTextを取得できてるよね?という確認の意味を込めて、StopWatchでの時間計測範囲外で、それぞれコンポーネントのTextデータもログ出力するようにしてみました。ログ全体を見やすくまとめてみると、以下のような結果になりました。▼▼▼GetObjectFind▼▼▼OK1回目:00:00:00.06180172回目:00:00:00.05935813回目:00:00:00.0615687▼▼▼GetObjectFindWithTag▼▼▼OK1回目:00:00:00.04180702回目:00:00:00.04354993回目:00:00:00.0441453▼▼▼GetChildrenObjectFind▼▼▼OK1回目:00:00:00.07299132回目:00:00:00.06946903回目:00:00:00.0693467▼▼▼GetChildrenObjectFindWithTag▼▼▼OK1回目:00:00:00.05400942回目:00:00:00.05554283回目:00:00:00.0556334▼▼▼GetObjectTransForm▼▼▼OK1回目:00:00:00.08751032回目:00:00:00.07835633回目:00:00:00.0798122結果について今回検証した内だと、GameObject#FindWithTag()を使用するのが最速であることが分かりました。Tagを指定して決め打ちなので、さもありなんといったところでしょうか。逆に親要素のオブジェクトを取得後、Transformを参照してどーのこーのやっているTransform#Find()が最も遅い結果となりました。面白いと思ったのが、親要素をFindWithTagで取得してやってから、その子要素をGetComponentInChildren()で取り出す手段が2番目に早いという点でしょうか。GameObject#FindWithTag()を使えばそりゃ早いけど、Tagの設定数が膨大になりそう......、といった時に、親要素分だけTagを設定し、子要素は親から取り出してやると言った手法が処理速度的にベターと言えそうです。おわりにとは言え、ゲーム制作で今回の検証で用いたように、一回一回GameObjectを取得して~コンポーネントを取り出して~、といった方法は用いないかな、と。そのシーン中で一度しか使わないようなオブジェクトに対しては、GameObject#FindWithTag()で十分でしょうが、一つのオブジェクトを複数回使い回す場合や、親要素と子要素どちらに対しても何かしら処理を行う場合など、場合によって使い分けが重要そうです。必要な場所ごとに、GetComponentInChildren()で取得とか。オブジェクトのTransformを何かしら弄りたい場合なんかは、むしろTransform#Find()が最適なのかもしれません。今適当に考えただけなので分かりませんが()ということで。取得方法』などでググるとよく目にする代表的(?)な手段について、検証してみました。これらの手段以外にももっと良い方法があるよ!などなどありましたら、教えて頂けると嬉しいです。GameObject#GetComponentInParent()はどうしたんだよ!という声は聞こえません。そんな感じで今回の記事を終えます。Screenで表示される問題を解決する方法Unityでゲーム開発がんばるぞ(学級目標)月別アーカイブプライバシーポリシーお問い合わせスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。