[unity] Prefab の落し穴

私はこれまで「とりあえず動けばいいや」と、フワッとした知識のまま言語や、ツールを使いながら色々なものを作ってきました。

ガチプログラマーの方には怪訝な顔をされるかもしれませんが、自分の楽しむのが一番だからね!

……と強がってみましたが、そんなアバウトな性格のせいで、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を「同じもの」と考えてしまったため、地味にハマった過去があるのでした。

なにかあった時はテスト用の新規プロジェクトを作って、きっちり試した方がいいですね!

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA