こんにちは、Unityエンジニアのオオバです。

お悩みさん
お悩みさん
  • TransformのFindってどんな機能?
  • Findは普通に使って良いもの?
  • オオバ
    オオバ
    本記事ではこれらの悩みを解決します。

    Transformとはオブジェクトの「移動」「回転」「大きさ」を管理するUnityの基本となるコンポーネント。
    もう1つの側面が 階層化 です。

    Hierarchyウィンドウ - 階層化のサンプル

    【Unity】TransformのFindメソッドを「おすすめしない」理由_0

    Transformは階層をいくつも作ることができ、オブジェクト配置するときに役立ちます。

    階層化で重要になるのは親子同士Transformの取得方法です。
    そのためにTransformにはいくつか取得メソッドが用意されています。

    本記事ではFindメソッドについて解説します。
    タイトルの通り、オオバの考えは Findメソッドの使用は禁止 です。

    開発におけるリスクが高い のが理由です。
    詳しくは以降の章で解説しています。ぜひ最後まで読んでみてください。

    TransformのFindは基本使用禁止

    結論から言うと、 TransformのFindメソッドは使用しないほうが安全 です。
    簡単にまとめるとこんな感じです。

    TransformのFindを使用禁止にする理由

    ①仕様変更に弱い

    ②プログラムの理解に時間がかかる

    まさにこの2点。
    詳しく解説していきます。

    👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!

    TransformのFindとは?

    使用禁止の話の前にTransformのFindについて解説します。

    Findとは簡単に自分の子階層を取得できるメソッドです。
    使い方は簡単。 A/B/C というパスを指定するだけ。

    例えば下記の構造のTransformを取得してみましょう。

    【Unity】TransformのFindメソッドを「おすすめしない」理由_1

    ルート階層の FindTransform に取得スクリプトをセットしています。

    こちらがスクリプトの抜粋です。
    Findメソッド の引数を色々と変えてみました。

    // 取得成功 → ○1階層下の子供は名前直指定でOK  
    var tr0 = transform.Find("Parent");  
    
    // 取得成功 → ○パスが適正  
    var tr1 = transform.Find("Parent/Child");  
    
    // 取得失敗 → ×パスが不正  
    var tr2 = transform.Find("Child/Grandchild");  
    
    // 取得失敗 → ×名前直指定  
    var tr3 = transform.Find("Grandchild");  
    

    結果は、ソースコードのコメントにに記載しています。

    子オブジェクトを取得するためには、
    Transformのパスを正確に指定する必要がある 点に注意してください。

    FindChildは非推奨

    昔はFindChildというメソッドがありました。

    しかし、現在は非推奨メソッドとなっております。

    いずれ削除されるので早々にFindメソッドに置き換えましょう。

    TransformのFindは使わないほうがいい

    早速Transformを使ってはいけない理由について解説します。
    Transformクラスの Findメソッド 自体は簡単に使えて、ちょっと便利だなって思いましたよね。

    しかし以下の理由から 実際のゲーム開発の現場では使えません

    TransformのFindメソッドの問題点

    ①仕様変更にもろい

    ②プログラムの理解に時間がかかる

    Findメソッドの問題点① 仕様変更にもろい

    あなたは新規のゲーム開発をしていたとします。
    開発中のゲームのデザインってコロコロ変わりますよね。

    いわゆる 仕様変更 です。

    それによって何が起きるかというと、
    GameObjectの階層もコロコロ変わってしまう ということです。

    つまりTransformのFindメソッドを使用すると、
    GameObjectの階層が変わるたびにソースコードも変えないといけない のです。

    数カ所なら良いですが、デザインの影響はゲーム全体です。
    デザイン修正のたびに、Transformの参照取得のためだけのソースコードを変更。

    非常に時間の無駄 なのです。

    Findメソッドの問題点② プログラムの理解に時間がかかる

    Findメソッドのパス指定にはもう1つのデメリットがあります。
    それは、 プログラムの内容理解に時間がかかってしまうこと です。

    どういうことかというと、Findで指定されたパスを読み解くために、
    Unityエディタとソースコードを何度も行ったり来たりする必要がある のです。

    この両者の行き来の回数は少なければ少ない方が良いのですが、
    パス指定によって回数が「爆増」するわけですね。

    結果的に内容を理解するために 膨大な時間 を要してしまうのです。

    【解決方法】事前のシリアライズ

    以上2つの理由からTransformのFindメソッドは使用禁止にしています。
    解決方法は事前のシリアライズです。
    すなわち、最初から参照関係を保持した状態にしておくということです。

    [SerializeField] private Transform _grandChild;  
    

    このように _grandChild を定義。

    【Unity】TransformのFindメソッドを「おすすめしない」理由_2

    そして事前にオブジェクトをセットしておきます。
    すると、 GameObjectの階層が変わったとしても参照が外れない のです。

    パス指定よりよっぽど簡単ですよね。

    シリアライズしたオブジェクトは「ピン」ですぐに発見

    シリアライズしたインスペクタを クリック してみてください。

    【Unity】TransformのFindメソッドを「おすすめしない」理由_3

    するとこのようにどのGameObjectをセットしているのか示してくれます。
    これがとっても便利なんです。

    ※Unity用語で「ピン」

    ピン によって一発でオブジェクトを検索できるので、
    パス指定方法と比べるとはるかにプログラムの理解は早くなります。

    ぜひFindを使っている箇所は上記の解決方法を使ってみてください。

    Transformには子階層のオブジェクトを取得する機能のほか、移動や回転といった重要な機能を持っています。
    ゲーム開発ではTransformの知識は必須 ということですね。
    ところで、Transformを網羅的に分かりやすく解説記事を書きました。
    ぜひ復習がてら読んでみてください。あなたの知らない機能が登場するかもしれません。

    まとめ

    TransformのFindメソッドについて解説してきました。

    TransformのFindまとめ

    ①FindはTransformの子階層を取得するメソッド

    ②実際の現場ではFindは使用禁止

    ③禁止理由1. 仕様変更に弱いため

    ④禁止理由2. プログラムの理解に無駄に時間がかかるため

    最終的に Findはおすすめできないメソッド です。
    例外があるとすると、キャラクターの骨構造の中の1つを取得したいといったケースです。

    キャラクタの手に何かを持たせたい、だからその手の骨のTransformを取得したい。
    そんな感じです。ただ、それも手の部分にスクリプトをセットしたほうが、安全な気もします。

    普通に使用する上ではあまり登場することはないメソッドであることは間違いない。
    もし、チーム開発でFindを見かけた際は注意。

    何かしら意図があるならOKですが、
    ただたんに使っているケースであれば 要注意 だということです。

    この記事があなたのUnity開発に役立つと嬉しいです。

    オススメ記事
    検証環境