オブジェクトの参照をセットする際の一番Unity的なアプローチは、Inspectorに露出してセットする事です。
ただ動的なオブジェクトとなるとInspectorは使いにくい所があります。この辺り、実際に正しい所もあるのですが、そうじゃない所もあります。
動的に増えるGameObjectですが、これが参照出来ない理由の大抵は「Prefabから元となるオブジェクトを持ってきている」為です。
PrefabはSceneのオブジェクトを参照できない
大抵のチュートリアルやサンプルでは、動的に増減する項目はResources等に配置したPrefabを取得し、Instantiateしています。
この方法はPrefabはScene内のオブジェクトにアクセス出来ないので、シーン内の参照関係を生成するコード等が担保する事になります。
例えば敵キャラクターを生成…みたいな場合、敵キャラクターはプレイヤーの位置やゲーム進行等の情報を得る必要があります。
ただPrefab等から生成する場合にはシーン内のオブジェクトにアクセス出来ないので、生成時にFindしてGameControllerを取得したり、Singletonパターンを使ったり、生成するコードが責任持って敵キャラクターに情報を流し込んだりします。
Scene内のオブジェクトもInstantiate出来る
ここでの勘違いは「InstantiateするオブジェクトはPrefabでなければならない」という点です。Instantiateは別に同じシーン内のオブジェクトに対しても実行が可能です。
同一シーン上で行うのであればInspectorで設定した参照をそのまま使えます。
ボタンのイベントや参照先は保持される
例えばUIのButtonの場合、「ボタンを押したら○○を呼ぶ」の挙動を維持したままボタンの数を増やせます。
どのボタンが押されたか…については、ボタンの引数にTransformを渡しておけば、Indexが取れるのでソレが使えます。
イベントや参照部分はScene上で設定できるので、コードはオブジェクトを生成する所だけ見れば良いです。
ここで面白いのが、生成時に「自分と同じオブジェクトもしくは子オブジェクト」への参照は、生成された場合も「自分と同じオブジェクトもしくは子オブジェクト」へ参照する点です。
なので上のGifアニメでは「自分のTransform」を参照すると、生成時に元となるTransformではなく「自分のTransform」を参照しています。
プレイヤーに向かって移動する敵を生成する例
例えば下のような、特定のオブジェクト(プレイヤー)に向かって移動する…といった物を考えてみます。当然プレイヤーに向かって移動するためにはプレイヤーの存在を知る必要があります。
初期段階
最初の段階のコードはこんな感じです。
ケース1:Prefabを使用した場合
これを動的に生成しようと思います。Prefabを使用した場合、生成側が責任を持ってプレイヤーを登録するか、移動するコードが生成してやる必要があります。
ただし敵の種類は一種類とは限らないため、インターフェースを利用して汎用的に使えるようにする必要があります。
逆に追跡側がプレイヤーを取得する場合、何度もFind等を使うのは望ましくない為、Staticなりに登録する必要が出てきます。
これはPrefabを使用する場合です。
ケース2:シーン内のオブジェクトを使用した場合
シーン内のオブジェクトを生成する場合、下のようなコードで上と同じように動作します。参照先の情報は既に持っているので、それを使えばOKな為です。
操作が必要になりますが、Prefabのケースと較べてかなりシンプルになっています。
生成元をテンプレートとして使いたいなら非アクティブなオブジェクト下に置く
GameObjectの生成してないのにAwakeが呼ばれて困る…みたいな場合には、親オブジェクトを非アクティブにしておくと良いです。
これでPrefabと同じような動きになります。
少し勘違いしやすい、Monobehaviourイベント関数の挙動の違い #unitytips pic.twitter.com/ZB8tuIyOBQ
— 椿 (@tsubaki_t1) 2018年2月27日
このアプローチの問題点は?
このアプローチで問題は、沢山のSceneで同じオブジェクトが沢山存在する場合、デシリアライズのコストが嵩むという点です。
ただ実際の開発ではシーン毎にユニークなオブジェクト…が割と普通で、共通部分があったとしてもパラメータをScriptableObjectに逃しておけば特に問題ないので、実はそこまでじゃないという話もあります(PrefabのパラメータもScriptableObjectに逃しておかないとInstantiate時のコストが結構あります)
それと、Inspectorの参照関係が壊れる的な話が時々上がりますが、自分は今のところ同一シーン内での参照関係が壊れた所を見た記憶が無いので、まぁ大丈夫かなと
(PrefabやAssetへの参照関係は、GUIDを変更しちゃう等で時々見ます)
どんな時に使えるの?
特定のシーンでしか使わないような物(UIや敵等)を複製したい場合には、シーン内の物を編集したほうが楽です。
逆に、複数のシーンで汎用的に使う物に関してはPrefabの方が便利かもしれません。
なおシーンはファイルが一つですのでマージの問題が出ますので、複数人で開発する場合はスマートマージを入れておいたほうが良いです。
その他
参照関係構築の為の記事を書いてたら補足項目なのに1000文字とか行ってたので分割…
Unity 4の時はシーンにPrefabの情報が直接書き込まれていたので、シーン内のPrefabにアクセスするのは少し躊躇われましたが、Unity 5からはシーンにあるのはPrefabへの参照と変化した値のみなので、特に気にせずアクセスしてもOK