前書き
Unityでゲーム開発を行う際、オブジェクトを検索する方法としてGameObject.Find関数やGameObject.FindWithTag関数を使用することが多いかなと思います。ただし、GameObject.Find関数はシーン内のオブジェクトをすべて検索するためコスパが悪い。GameObject.FindWithTag関数はタグをつける必要があるため、Playerなどユニークなオブジェクトなら利用できますがいろいろ取得したい場合には不向き。っといったことがあげられます。
いままでFindWithTag関数ばかり使っていたのですが、Transform.Find関数を使用することで子オブジェクトの指定なども簡単に出来たため今回はTransform.Find関数について紹介していこうと思います。
Find関数の種類
よく使われるFind関数として以下の3つがあげられます。
GameObject.Find
GameObject.FindWithTag
Transform.Find
それぞれについて簡単に説明していきます。
GameObject.Find
用途: シーン内の特定の名前を持つオブジェクトを検索するために使用します。
特徴:
- 名前に依存するため、オブジェクトの名前が変更された場合や同じ名前のオブジェクトが複数存在する場合に問題が発生することがあります。
- シーン全体を検索するため、大規模なシーン(オブジェクトの数が膨大)だと検索に時間がかかるためパフォーマンスに影響を与える可能性があります。
GameObject.FindWithTag
用途: 特定のタグを持つオブジェクトを検索するために使用します。
特徴:
- タグを使用するため、名前に依存せずにオブジェクトを検索できます。
- タグはプロジェクト内で一意である必要がありますが、同じタグを持つ複数のオブジェクトを検索することも可能です。
- 全体検索をしないためパフォーマンスはGameObject.Findよりも優れていますが、多数のタグ付きオブジェクトが存在する場合には影響が出ることもあります。
Transform.Find
用途: 特定の親オブジェクトの子オブジェクトを検索するために使用します。
特徴:
- 親オブジェクトの子オブジェクトのみを検索するため、シーン全体を検索するGameObject.Findよりも効率的です。
- 階層構造を意識した検索が可能で、特定の親オブジェクト内に限定してオブジェクトを見つける場合に便利です。
- 名前に依存するため、子オブジェクトの名前が変更された場合には問題が発生することがあります。
Transform.Findのここがいい
Transform.Findは親オブジェクトと子オブジェクトの階層構造を利用するため、特定の親オブジェクト内でのみ検索を行います。これにより、意図しないオブジェクトが検索されるリスクを減らすことができます。特に、同じ名前のオブジェクトが複数存在する場合に有効です。
使い方としてインスペクターからオブジェクトを設定したり、検索するため事前にオブジェクトを取得する必要はありますが、取得したオブジェクトを元にFindを行うことでシーン全体でFindをする必要がなく、GameObject.Findよりもはるかにコスパはよくなります。また、GameObject.FindWithTagとTransform.Findを上手く組み合わせればGameObject.Findと同等レベルまでオブジェクトの検索をすることができます。
Transform.Findをどのように使っているか
ソースコードを簡単に貼り付けましたが、上記のようにtransform.Findを使用してコンポーネントを取得しています。
使い方としては
- TotalStatsPanel(親オブジェクト)を取得
- TotalStatsPanelの子オブジェクトであるTotalAttackContainerなどをFindで指定し、選択する
- GetComponentで各種オブジェクトのコンポーネントを取得していろいろと処理を実装する
いままではどうにかしてコンポーネントを取得していましたが、現在は親オブジェクトをPublicで取得し、上記のようにパスで指定して子オブジェクトをまとめて取得している方法をとっています。この方法だとGameObject.FindよりコスパもよくGameObject.FindWithTagでタグを付与しなくてもオブジェクトを特定することができます。
ただし、先の説明でも記載しましたがこの方法だと名前に依存するため、子オブジェクトの名前が変更された場合には問題が発生します。コーディング段階ではパスやオブジェクトの名前が正しいかは判断できないためコンパイルは普通に通ります。実行した時に初めてエラーになるためエラーの解析がちょっと面倒というデメリットはあると思いますが、オブジェクトを一意に特定する方法としてはTransform.Findがいいかなと思っています。
まとめ
今回はTransform.Find関数を使って対象のオブジェクトを見つける方法について紹介しました。
オブジェクトを検索する方法はいろいろあると思いますが、いずれにしてもケースバイケースの使い方になると思います。とはいえ、個人的にGameObject.Findを使ってシーン内のオブジェクトを全検索することはあんまりないかなと思っています(例えば、Pause画面中などで処理が中断しているときは有りだと思います。)
今回紹介した方法を使えば(Publicで親オブジェクトを指定する手間はありますが)、効率よくオブジェクト検索ができると思います。
処理が軽いほうがゲームも快適に出来るためもしGameObject.Findを使って検索している所があったらGameObject.FindWithTagや今回紹介したTransform.Findの方法で出来ないか処理の改善を検討してみてください。
コメント