書いてたら長くなったので結論だけ先書いときます。
- Instantiateで生成されるオブジェクト名は語尾に(Clone)が付く
- GetComponentだと子のオブジェクトまで探してくれない
- GameObject.Findは同名オブジェクトが複数あるとHierarchyから見て一番上の奴しか取ってこない
色々解決すべき点があるので順にやっていきましょう。
1: Instantiateで生成されたオブジェクト名について
var obj = Instantiate(hogehoge, canvas.transform) as GameObject;
var hogebutton = GameObject.Find("Button").GetComponent<Text>();
(hogehogeオブジェクトの名前が分かりませんがひとまず"Button"として話を進めますね。)
hogehogeという変数に格納されたボタンをInstantiateで生成し、直後に"Button"という名のオブジェクトを探しその中にあるTextコンポーネントを取り出そうとしていると思います。
ですが生成されたオブジェクトは、元々のオブジェクト名 + "(Clone)"という名前に変化します。
元々"Button"って名前なら"Button(Clone)"になりますね。
var obj = Instantiate(hogehoge, canvas.transform) as GameObject;
var hogebutton = GameObject.Find("Button(Clone)").GetComponent<Text>();
2: Buttonに含まれるTextコンポーネントの階層について
var hogebutton = GameObject.Find("Button(Clone)").GetComponent<Text>();
これでGameObject.Findで無事ボタンオブジェクトを取得出来、TextもGetComponentで取得!..出来ないんです。
最初にButtonをPrefab化する為にHierarchy欄にて、Buttonを新規作成すると思いますが階層が以下のようになっています。(括弧内にその階層に付与されているコンポーネントを記載)
Button (RectTransform/CanvasRenderer/Image/Button)
└Text (RectTransform/CanvasRenderer/Text)
Textコンポーネントが親(Button)ではなく子(Text)に付与されているのが分かります。
ここが原因であり、GetComponentは探してきて欲しいオブジェクトから指定したコンポーネントを探してきてくれます。
GameObject.Find("Button(Clone)")は一番上のButtonオブジェクトから探しますが、子のTextオブジェクトは探索外になります。
解決策としては、子もまとめて探索してくれるGetComponentInChildren, Textコンポーネントが含まれているTransformを渡し探す等あります。
// こちらの方がおススメ (処理が重いので毎フレーム使ったりするのは非推奨)
var hogebutton = GameObject.Find("Button(Clone)").GetComponentInChildren<Text>();
// Button(Clone)の0(1)番目の子供を取り、そこからGetComponentで探す
var hogebutton = GameObject.Find("Button(Clone)").transform.GetChild(0).GetComponent<Text>();
3: 同名のオブジェクトがある時のGameObject.Findの挙動
var hogebutton = GameObject.Find("Button(Clone)").GetComponentInChildren<Text>();
これで"Button(Clone)"オブジェクトの(子も含め)Textコンポーネントを探してくる処理になりました。
ですがまだ上手くいきません。具体的には一つのTextしか変化していないと思います。
理由としてはGameObject.Findが毎回同じオブジェクトを取ってきてしまうからです。
GameObject.FindはHierarchyの一番上から下まで順に名前で検索し合致していればそのオブジェクトを取ってきます。
さらにInstantiateで生成し、同じ階層に設置したオブジェクトは前に生成されたオブジェクトの下に生成されます。 つまり...
1. 1つめのButtonが生成される
Canvas
└Button(Clone)
2. GameObject.Findが上から順に"Button(Clone)"を探す
Canvas ← 名前が違う
└Button(Clone) ← これだ!
3. 取ってきたTextを変更する (1つめのButtonオブジェクト内のText)
4. 2つめのButtonが生成される
Canvas
├Button(Clone)
└Button(Clone) ← 新しいButton
5. GameObject.Findが上から順に"Button(Clone)"を探す
Canvas
├Button(Clone) ← 名前合ってるなこいつ取ってきます!
└Button(Clone) ← (本当はこいつから取ってきて欲しい)
6. 取ってきたTextを変更する (また1つめのButtonオブジェクト内のText)
7. 以下略
...という訳で毎回一番上である1つめのボタンオブジェクトからTextを取ってきてしまいます。
対処法としてはそもそもGameObject.Findを使わず、出来立てホヤホヤのButtonを取りましょう、というより投稿者様が挙げたコード内で既に取ってます。
var obj = Instantiate(hogehoge, canvas.transform) as GameObject;
実はInstantiateは作ったオブジェクトを渡してくれます。
上の1行だと var objに出来立てのButtonオブジェクトが入っています。
と言う事はわざわざGameObject.Findなんてしなくても...
var obj = Instantiate(hogehoge, canvas.transform) as GameObject;
var hogebutton = obj.GetComponentInChildren<Text>();
これで片付きます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/01/02 15:54
2022/01/06 07:57
2022/01/06 08:11
2022/01/06 08:45 編集
2022/01/07 16:48