ゲームには欠かせない、メニュー画面や文字、ボタンなどのUI。
それらを配置するために、Unityでは「Canvas」というオブジェクトを親にして配置します。
今回は、このキャンバスをスクリプトから取得/生成する方法をお伝えします。
スクリプトからCanvasを操作することで、キー操作で表示、非表示を切り替えたり、必要な場面で生成できたりします。
Canvasの取得方法
まずは、上画面のようにCanvasの情報を取得する主な2つの方法を紹介したいと思います。
他にも方法はありますが、初心者にもわかりやすく簡単で汎用性の高い方法をお伝えします。
2つのどちらの方法でも上画面のように、インスペクター上に設定されます。
Canvasのオブジェクトをインスペクターにドラッグアンドドロップできるようにする。
Publicというアクセス修飾子を使ってインスペクター上で直感的にドラッグアンドドロップできるようにする方法です。
これから、インスペクター上に設定できるようにした後に、取得したCanvasをエスケープキーで表示、非表示を繰り返せるようにしましょう。
上記画面のように、ヒエラルキーのプラスボタン→UI→キャンバスの順でクリックしてください。
そうすると、CanvasとEventSystemというオブジェクトが生成されます。
ここではEventSystemについては詳しくは話しませんが、EventSystemがないと、ボタンなどの操作行うUIが反応しなくなるので消さないようにしましょう。
Canvasを作成したら、次はUIを適当に配置してみましょう。
今回はメニュー画面のようなイメージなので、先ほどと同様に、ヒエラルキーのプラスボタン→UI→パネルやボタンを作って以下のようなUIを作りました。
同じような手順で他のUIも作ることができます。
配置の仕方や大きさの変更、テキストの設定などは本筋ではないので、今回は具体的に話しませんが、様々なカスタマイズが可能なので、気になったらぜひやってみましょう。
UIの配置は本筋ではないので、適当に作ってもらって構わないですが、最低限目に見えるようにパネルだけは作成しましょう。
次は、空のオブジェクトを作ります。
ヒエラルキーのプラスボタンまたは、ヒエラルキー上で右クリック→空のオブジェクトを作成します。
その空のオブジェクトをGameManagerという名前にします。
名前はなんでも良いではあるのですが、メニュー画面のようなUIの表示、非表示の切り替えは、裏方的なものでゲームシステムを支えるものなので、このように空のオブジェクトにひとまとめにすることが多いです。
よって、この名前にしています。
このGameManagerにCanvasを取得できるスクリプトを設定します。
次は、プロジェクトのプラスボタンまたは、プロジェクト上で右クリック→作成→C#スクリプトを作成します。
こちらも名前はなんでもいいっちゃいいですが、今回はGetCanvasにします。
上GIF画像のように、作成して名前をすぐ変更できるタイミングで名前を変更してください。
では、以下のスクリプトコードを書いていきましょう。
- using UnityEngine;
- public class GetCanvas : MonoBehaviour
- {
- //Publicというアクセス修飾子をつけることで、インスペクター上に公開される。
- //Canvasを取得するための型がCanvas。canvasは変数。ここは個人で変えてよし。
- public Canvas canvas;
- private void Start()
- {
- //ゲームがスタートした瞬間にキャンバスの表示をオフ。
- canvas.enabled = false;
- }
- // Update is called once per frame
- private void Update()
- {
- //キーボードのエスケープキーを押したら
- if (Input.GetKeyDown(KeyCode.Escape))
- {
- //非表示の時は、表示する。表示されている時は、非表示にする。
- canvas.enabled = !canvas.enabled;
- }
- }
- }
コードの解説はのちほど行います。
まず、スクリプトを書いたら、先ほど作ったGameManagerにドラッグアンドドロップします。
その後、キャンバスをドラッグアンドドロップで設定します。
では、ゲームを再生して、ゲームの画面をクリックして、何回かエスケープキーを押してみましょう。
エスケープキーを押すと、メニュー画面のようにUIの表示、非表示を切り替えができたと思います。
では、先ほどのコードの解説です。
7行目のこちらのスクリプトでは、Canvas型の変数canvasを、publicというアクセス修飾子で、他のスクリプトからでも直接値を変更できるようになっています。
Canvasのオブジェクトを格納できる変数を用意して、publicでインスペクター上設定できるようにしているというイメージです。
このコードと、エディター上の操作でCanvasを取得しています。
- private void Start()
- {
- //ゲームがスタートした瞬間にキャンバスの表示をオフ。
- canvas.enabled = false;
- }
- // Update is called once per frame
- private void Update()
- {
- //キーボードのエスケープキーを押したら
- if (Input.GetKeyDown(KeyCode.Escape))
- {
- //非表示の時は、表示する。表示されている時は、非表示にする。
- canvas.enabled = !canvas.enabled;
- }
- }
その他のコードに関しての解説をします。
Void Startは、ゲームが再生した瞬間に〜するというコードです。
Startの中身は、canvasという変数の、Canvasというコンポーネントをfalseにしているという機能になっています。
Void Updateは、ゲーム中に〜するというコードです。
そして、if (Input.GetKeyDown(KeyCode.Escape))は、エスケープキーを押したら〜するというコードです。
その中身は、canvas.enabled =!canvas.enabled;で、canvas.enabledは、表示中、その前に!をつけると非表示という意味になります。
つまりまとめると、ゲーム中にエスケープキーを押すと、canvasが非表示だったら表示にし、表示中だったら非表示にするいう機能になるということです。
タグやオブジェクトの名前から検索して取得
次は、GetCanvasのコードを少しだけ改良して、ドラッグアンドドロップという操作をしなくてもいいようにしましょう。
Void startの中身を以下のコードに変更してください。
- private void Start()
- {
- //ゲームがスタートした瞬間にキャンバスの表示をオフ。
- canvas.enabled = false;
- }
- // Update is called once per frame
- private void Update()
- {
- //キーボードのエスケープキーを押したら
- if (Input.GetKeyDown(KeyCode.Escape))
- {
- //非表示の時は、表示する。表示されている時は、非表示にする。
- canvas.enabled = !canvas.enabled;
- }
- }
このコードを書くことで、先ほどのようにドラッグアンドドロップしてインスペクター上で設定する必要がなくなります。
このように、ゲームを再生するだけで勝手に取得してくれます。
GameObject.Find("オブジェクトの名前").GetComponent<そのオベジェクトについているコンポーネント>();
このように入力すると、GameObject.Find()は、その名前のオブジェクトを取得し、GetComponent<>は、それについているコンポーネントを取得してくれます。
次はタグから取得しましょう。 まず、CanvasのオブジェクトにCanvasというタグをつけます。
つけたら、void Startの中身のコードを以下のように書き換えましょう。
- private void Start()
- {
- // Canvasのタグが付いたオブジェクトを検索して取得し、canvas変数に格納する
- GameObject canvasObject = GameObject.FindWithTag("Canvas");
- canvas = canvasObject.GetComponent<Canvas>();
- // ゲームがスタートした瞬間にCanvasの表示をオフにする
- canvas.enabled = false;
- }
GameObject.FindWithTag("タグの名前");で、タグに設定した名前と同じオブジェクトを取得します。 その後は、先ほどと同じような機能をしています。
Canvasの生成方法
先ほどは、ヒエラルキー上にあるCanvasを取得して表示、非表示にしていましたが、次からはCanvasを生成してしまいたいと思います。
プレハブにしたのち、インスタンス生成
こちらは、先ほど作ったCanvasオブジェクトをプレハブにして生成する方法です。
まず、上記GIF画像の作業をしてプレハブ化してください。
プレハブ化は、オブジェクトをたくさん置きたい時や、これから行うように、特定の動作をした時に生成したい時に便利です。
では、ヒエラルキー上のCanvasを削除して、先ほどのGetCanvasを書き換えましょう。
- public class GetCanvas : MonoBehaviour
- {
- // Canvasのプレハブを格納する変数
- public GameObject canvasPrefab.
- Canvas canvas;
- private void Start()
- {
- // Canvasのプレハブを生成してcanvasObject変数に格納する
- GameObject canvasObject = Instantiate(canvasPrefab);
- // 生成されたCanvasを取得し、canvas変数に格納する
- canvas = canvasObject.GetComponent<Canvas>();
- // ゲームがスタートした瞬間にCanvasの表示をオフにする
- canvas.enabled = false;
- }
- //以下は同文
書き換えたのちは、プレハブを設定しましょう。
ゲームを再生すると、ヒエラルキー上にCanvas(clone)が生成され、エスケープキーで表示、非表示の切り替えができるはずです。
では、コードの解説に移ります。
- // Canvasのプレハブを格納する変数
- public GameObject canvasPrefab;
6行目は、publicでインスペクター上に設定できるようにしたのち、GameObjectの型の変数に格納できるようにしています。
- // Canvasのプレハブを生成してcanvasObject変数に格納する
- GameObject canvasObject = Instantiate(canvasPrefab);
- // 生成されたCanvasを取得し、canvas変数に格納する
- canvas = canvasObject.GetComponent<Canvas>();
ここでは、先ほど格納したcanvasPrefabをInstantiateで生成しています。
Instantiate(生成したいオブジェクト)で生成できます。
そして、生成したオブジェクトをcanvasObjectに格納したあと、それをcanvas変数に格納し、Canvasのコンポーネントを取得しています。
その後は同様です。
2.ゲーム再生した瞬間に生成
次は、プレハブからでもではなく、何もない状態からスクリプトからCanvasを作成します。
GIF画像のような挙動を作りたいと思います。
Canvasとtextを生成し、画面上に「I’m a perfect human」を表示させています。
まず、下準備として、プロジェクト上で右クリック→作成→フォルダーでResourceという名前を作成し、その中にフォントを入れます。
私の場合は、TextMeshProの初期フォントを複製して入れています。
では、新たにCanvasManagerというスクリプトを作成し、先ほどまでアタッチしていたGetCanvasのスクリプトはGameManagerから外しておいてください。
それでは、以下のスクリプトを書いてみましょう。
- using UnityEngine;
- using UnityEngine.UI;
- public class CanvasManager : MonoBehaviour
- {
- // 既存のキャンバスへの参照
- private Canvas existingCanvas;
- void Start()
- {
- // 新しい空のゲームオブジェクトを作成し、名前を設定する
- GameObject myGO = new GameObject();
- myGO.name = "TestCanvas";
- // ゲームオブジェクトにCanvasコンポーネントを追加する
- Canvas myCanvas = myGO.AddComponent<Canvas>();
- //Canvasのレンダーモードをオーバーレイに設定
- myCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
- // ゲームオブジェクトにCanvasScalerコンポーネントを追加する
- myGO.AddComponent<CanvasScaler>();
- // ゲームオブジェクトにGraphicRaycasterコンポーネントを追加する
- myGO.AddComponent<GraphicRaycaster>();
- // テキストを作成し、キャンバスの子オブジェクトにする
- GameObject myText = new GameObject();
- myText.transform.SetParent(myGO.transform); // SetParent メソッドを使用して親を設定
- myText.name = "wibble";
- // テキストコンポーネントを追加し、設定する
- Text text = myText.AddComponent<Text>();
- //Resoucesフォルダにあるものをとってくる。
- text.font = (Font)Resources.Load("LiberationSans 1"); // テキストのフォントを設定する
- text.text = "I'm a perfect human"; // テキストの内容を設定する
- text.fontSize = 100; // テキストのフォントサイズを設定する
- // テキストの位置を設定する
- RectTransform rectTransform = text.GetComponent<RectTransform>();
- rectTransform.localPosition = new Vector3(100, -300, 0); // テキストのローカル位置を原点に設定する
- rectTransform.sizeDelta = new Vector2(1000, 1000); // テキストのサイズを設定する
- }
- }
このスクリプトをGameManagerにアタッチしたら先ほどのように画面上にテキストが現れるはずです。
では、スクリプトを見ていきます。
- // 新しい空のゲームオブジェクトを作成し、名前を設定する
- GameObject myGO = new GameObject();
- myGO.name = "TestCanvas";
void CreateCanvas()の中身が主な挙動なのでこちらから見ていきます。
Canvasは、Cubeのようなオブジェクトではなく、コンポーネントなので、GameObject.つけたい名前=new GameObject()で、空のオブジェクトを作成したのちに、次のコードでCanvasに必要なコンポーネントを付与しています。
- // ゲームオブジェクトにCanvasコンポーネントを追加する
- Canvas myCanvas = myGO.AddComponent<Canvas>();
- //Canvasのレンダーモードをオーバーレイに設定
- myCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
- // ゲームオブジェクトにCanvasScalerコンポーネントを追加する
- myGO.AddComponent<CanvasScaler>();
- // ゲームオブジェクトにGraphicRaycasterコンポーネントを追加する
- myGO.AddComponent<GraphicRaycaster>();
AddComponet<つけたいコンポーネント>()でコンポーネントを付与できます。
MyCanvas.renderMode = RenderMode.ScreenSpaceOverlay;は、Canvasの設定を変更しています。
これらのスクリプトが、Canvasを生成するためのメインのコードで、それ以外のコードは補助的なコードになります。
次は、テキストを作成するスクリプトの解説をします。
- / テキストを作成し、キャンバスの子オブジェクトにする
- GameObject myText = new GameObject();
- myText.transform.SetParent(myGO.transform); // SetParent メソッドを使用して親を設定
- myText.name = "wibble";
- // テキストコンポーネントを追加し、設定する
- Text text = myText.AddComponent<Text>();
- //Resoucesフォルダにあるものをとってくる。
- text.font = (Font)Resources.Load("LiberationSans 1"); // テキストのフォントを設定する
- text.text = "I'm a perfect human"; // テキストの内容を設定する
- text.fontSize = 100; // テキストのフォントサイズを設定する
- // テキストの位置を設定する
- RectTransform rectTransform = text.GetComponent<RectTransform>();
- rectTransform.localPosition = new Vector3(100,-300,0); // テキストのローカル位置を原点に設定する
- rectTransform.sizeDelta = new Vector2(1000,1000); // テキストのサイズを設定する
ここでは、myTextという空のオブジェクトを作成したのち、myTect.transform.SetParent(親にしたいオブジェクト.transform)で、myGOをオブジェクトの親に設定できます。
Text text = myText.AddComponent<Text>()で、Textのコンポーネントを付与。
次に先ほど作成したResoucesフォルダの中にあるフォントを設定するために、text.fontに、(Font)Resources.Load("設定したいフォント");でフォントを設定しています。
他のコードも同様、textのコンポーンネントの値に干渉しています。
まとめ
- publicを使って、Canvas型の変数にインスペクター上からドラッグアンドドロップで設定。
- Find("オブジェクトの名前")で、オブジェクトの名前から取得、または、GameObject.FindWithTag("Canvasについているタグの名前");で、付いているタグから取得。
- Instantiate(プレハブ化したCanvasを格納した変数);でプレハブから生成
- new GameObject()で、空のオブジェクトを作成したのち、AddConponent<Canvas>()などでコンポーネントを付与してCanvasを作成。
今回は、簡単にCanvasを取得、生成しましたが、UIはまだまだいろんな機能を持っています。
また、UIをカスタマイズすることでゲームとしての完成度がかなり変わってくるので、もっと知識をつけて、面白くて雰囲気のよいゲームを作っていきましょう!
参考サイト: