【Unity】一部変更したプレハブを生成するときの落とし穴

2021年5月4日火曜日

C# Unity Unity2D

この記事をシェアする
  • B!

上の画像は、現在開発しているゲームに作った、よくあるクエスト一覧です。
達成したクエストから灰色に染まる、みたいな感じになってます。
これを開発中のことですが、UIのプレハブ生成で少し詰まるところがありました。

例えばこのクエスト一覧の場合、上の一個だけ灰色で、他は白色のまま生成ということになります。
こういうのはどうやって実装するのか?今回はその方法の紹介になります!


ブログランキング・にほんブログ村へ にほんブログ村 IT技術ブログへ にほんブログ村 IT技術ブログ Unityへ にほんブログ村 IT技術ブログ C#へ

環境について

Unityバージョン:2019.4.18f1
Visual Studio Community 2019バージョン:16.9.1

間違ったプレハブの扱い方

少し詰まるところがあった、とたった今書いたところですが、
ではどこで詰まったのか、という話をまずさせてください。

①まずは状況を準備

とりあえず類似状況から作りましょう。
画像のような状況を想像してください。


何か説明するほどのことでもないですが、
 ①Canvas作って
 ②Panel作って
 ③PanelにVertical Layout Group(垂直レイアウトグループ)をつけて子のUIを下一列に並べられるようにして
 ④Panelの子オブジェクトにボタンを作って
 ⑤ボタンが③でつけたVertical Layout Groupを無視できるようにLayout Element(layout要素)コンポーネントを弄って…

 って感じです。
 ボタンを押したら、Panelの子にプレハブを生成しよう、という思惑ですね。

作るプレハブは適当にこんな感じに。


Imageの子にTextをつけただけの簡単なUIです。
いい感じに作って、プロジェクトウィンドウにドラッグ&ドロップ、プレハブ化させたら配置準備完了!

②間違ったスクリプト

ではさらっとスクリプトをば。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PrefabInstance : MonoBehaviour
{
    GameObject Element;
    Image image;
    Text text;
    // Start is called before the first frame update
    void Start()
    {
        Element = Resources.Load("Image") as GameObject;
        image = Element.GetComponent();
        text = Element.transform.Find("Text").GetComponent();

    }

    public void OnClickButton()
    {
        Instantiate(Element, this.transform);
        image.color = Color.gray;
        text.text = "胡蝶の夢のプログラミン";
    }

んな感じでスクリプト書いて、Panelに張り付けて、ボタンにもちゃんと設定しておいたら大丈夫でしょ!

はい、レッツゲームスタート!ボタンクリック!


…え?
あれ?Textちゃんといれたんだけどな?色も変えたはずなんだけどな…?

というような事態に陥り、少しばかり私は悩んでしまいました。

正しいプレハブの扱い方について

ということで浮上しました、「プレハブ変更したのに反映されない問題」ですが、これって別に何かエラーが起きてるわけでもなくて、こちら側(人間側)の理解が追い付いてないだけだった、というのが私の結論です。

そうですね、例えばこの状況、もう一度ボタンを押すとどうなるのかというとこうなります。


二つ目からはちゃんと適用されています。

もうこれだけで、勘のいいひとは気づくかもしれません。

先に紹介した、私のスクリプトのロジックを文字化すると、下記のようになります。

1.プレハブを取得
2.プレハブのimageコンポーネントを取得
3.プレハブの子オブジェクトのTextのtextコンポーネント取得
4.プレハブ生成
5.生成したプレハブの色を変える
6.生成したプレハブの子オブジェクトのテキストを代入


スクリプトには特にエラーは出ていなかったので、このロジックの通りに処理自体はされているのは確かです。
しかし一個目のプレハブでは5と6が適用されず、二個目から適用、ということは、こうすればできるんじゃないか?と思い浮かぶ案が一つあるのではないでしょうか。

1.プレハブを取得
2.プレハブのimageコンポーネントを取得
3.プレハブの子オブジェクトのTextのtextコンポーネント取得
4.生成したプレハブの色を変える
5.生成したプレハブの子オブジェクトのテキストを代入
6.プレハブ生成


これだろう!

    //中略
    public void OnClickButton()
    {
        image.color = Color.gray;
        text.text = "胡蝶の夢のプログラミン";
        Instantiate(Element, this.transform);
    }

結果はこちら。


はい、うまくできました!

最後に

プレハブを一部変更して生成する場合の考え方ですが、生成した後にプレハブの一部を変更、ではなくて、取得したプレハブを変更してから生成、が正しい考え方のようだ、というのが今回ご紹介した内容のポイントですね。
もう少し深く考えると、プレハブをいちいち変更して出すということは、そのプレハブを使いまわす場合に各回で変更部分のリセットも併せてする必要性も理解しておくべきかもしれません。プレハブの生成には今後、十分注意して取り組むことにしようと思います。

ブログランキング・にほんブログ村へ にほんブログ村 IT技術ブログへ にほんブログ村 IT技術ブログ Unityへ にほんブログ村 IT技術ブログ C#へ

自己紹介

自分の写真
大学では文学部日本文学科出身という生粋の文系。チャットゲームの運営の在宅業務に携わったことでプログラミングに興味を持ち、2020年末、SAMURAI ENGINEERに入塾。2021年4月末に卒塾。 ※お問い合わせある方は、ブログのお問い合わせページからどうぞ~

ページビューの合計

応援をお願いします!

もしよかったらTwitterのフォローと応援ポチをよろしくです~
PVアクセスランキング にほんブログ村
ブログランキング・にほんブログ村へにほんブログ村 IT技術ブログへにほんブログ村 IT技術ブログ Unityへ
にほんブログ村 IT技術ブログ C#へ

QooQ