私はこれまで「とりあえず動けばいいや」と、フワッとした知識のまま言語や、ツールを使いながら色々なものを作ってきました。
ガチプログラマーの方には怪訝な顔をされるかもしれませんが、自分の楽しむのが一番だからね!
……と強がってみましたが、そんなアバウトな性格のせいで、Prefab についても深く理解しないまま使い、ちょっとした落とし穴にハマったことがあります。
似たような人には役立つかもしれないので、記事にしておきます。
その1 動くサンプル
実験するために色々用意しました。
まず、Text だけのプレファブ(TestPrefabObject)をシーンに配置し、SampleA オブジェクトにアタッチします。
SampleA のコードは、テキストの中身を変えるだけ。
using TMPro; using UnityEngine; public class Sample : MonoBehaviour { [SerializeField] GameObject TestPrefab; void Start() { var text = TestPrefab.GetComponentInChildren<TextMeshProUGUI>(); text.SetText($"{this.name}"); } }
実行すると "SampleA" が表示されます。
その2 動かないサンプル
その1とほとんど同じですが、今度はシーンに置いてある TestPrefabObject ではなく、アセットにある TestPrefab をアタッチします。
このまま実行すると、今度は表示されません。
(特にエラーも表示されない)
この理由ですが、TestPrefab の段階では「使う準備が整っていない」ということです。
使えるようにするためには、Hierarchy(シーン)に実際に配置する必要があります。
(その1では自分で配置していたため、動作したのです)
プログラムで配置するためには Instantiate を行います。
using TMPro; using UnityEngine; public class Sample : MonoBehaviour { [SerializeField] GameObject TestPrefab; void Start() { var gameObject = Instantiate(TestPrefab, this.transform); var text = gameObject.GetComponentInChildren<TextMeshProUGUI>(); text.SetText($"{this.name}"); } }
「その1」で Instantiate した場合……
この場合、シーンに元からいた Prefab と、新たに作成された Prefab の2つになってしまいます。
(Clone) がついている方が Instantiate された Prefab です。
まとめ
知ってしまえば理にかなったルールなのですが、私はその1とその2を「同じもの」と考えてしまったため、地味にハマった過去があるのでした。
なにかあった時はテスト用の新規プロジェクトを作って、きっちり試した方がいいですね!