竜太のテクニカルメモ

物理やへっぽこなゲーム作りについて易しく解説するよ

ユニティちゃんライセンス

このブログはユニティちゃんライセンス条項の元に提供されています

Unityで3Dのゲームを作る(9)

前回はPaddleにCylinderが衝突するとCylinderが消滅するようにしました.今回はよりゲームらしくPaddleにCylinderが衝突するたびにScoreが1点ずつ加算されるようにしましょう.そのためにはまずScoreを表示するUIを用意しなければなりません.まずHierarchyビューで[Cretate]→[UI]→[Panel]を選択します.自動的にCanvasができ,その下にPanelもできます:

f:id:lagrangian:20210128173054p:plain
Canvasの下にPanelができる
このときSceneビューを確認するとPanelを表す半透明の白い領域が画面の右の方にできているはずですが,一見すると位置が悪いように見えます:
f:id:lagrangian:20210128173639p:plain
SceneビューではPanelの位置が悪いように見える
これはCanvasのRender ModeがデフォルトではScreen Space - Overlayになっているときに起きるのですが,Overlay表示はCameraの位置に関係なく常に画面全体の最前面に広がるので正しい挙動です.今回もScoreやGAME OVERの表示は画面全体を基準として最前面に表示したいので,このScreen Space - Overlayの設定を使用します.この状態でゲームをPlayすると曇りガラスのようなPanelが前面に表示されるはずです:
f:id:lagrangian:20210128174709p:plain
PanelのOverlay表示
さて,Panelは色々なコントロールを配置するためのものです.実は今回の場合,なくてもよいのですが,今後色々なコントロールを配置することも考えられますので使ってみました.今回はこのPanelにText Mesh ProでScoreを表すテキストを配置してみましょう.HierarchyビューでCanvasの下のPanelをクリックして右クリックのコンテキストメニューから[UI]→[Text - TextMeshPro]を選択します.するとTMP Importerウィンドウが現れますのでImport TMP EssentialsをクリックしてText Mesh ProのAssetをインポートします:
f:id:lagrangian:20210131172055p:plain
Text Mesh ProのImporter画面
ProjectビューのAssetsフォルダにTextMeshProがインポートされますので,TMP Importer画面は閉じておきましょう.

するとPanelの下にText (TMP)ができますので,ScoreTextにリネームしておきましょう:

f:id:lagrangian:20210128180024p:plain
Text(TMP)をScoreTextにリネーム
次にScoreTextを選択した状態でInspectorビューのTextのテキストエリアに書かれた"New Text"の文字を"Score:"に書き換えておきましょう.この状態でPlayボタンを押すと次のようになるはずです:
f:id:lagrangian:20210128180705p:plain
中央にScore:の表示が出た
きちんと"Score:"の文字が出ました.ただし,位置や文字色は変えたいし,ゲーム中ずっと半透明のPanel越しにPlayするのは嫌なので,Panelは完全に透明にし,"Score:"テキストの位置や色やフォントサイズは変更しておきましょう.

まずはPanelの完全透明化です.HierarchyビューでCanvasの下のPanelをクリックしてInspectorビューのImage (Script)の欄のColorの右のカラーバー(デフォルトでは白い)をクリックします.カラーピッカーが立ち上がります:

f:id:lagrangian:20210128181952p:plain
ColorPickerでAlpha値を0にする
RGBの下のAと表示されている部分はAlpha値を表し,Alpha値は0が完全に透明,255が完全に不透明になりますので今回は0に設定します.これでこのPanelは完全に透明になりました:
f:id:lagrangian:20210128183110p:plain
SceneビューでPanelの透明化を確認
この状態でPlayボタンを押すと当然画面は半透明な曇った表示ではなくなっていることが分かります:
f:id:lagrangian:20210128183509p:plain
GameビューでPanelの透明化を確認
Panelの透明化が終わったので次にScoreTextの調整に入ります.まず,HierarchyビューでCanvasをダブルクリックします.すると遠くからOverlay表示する白枠が見えるはずです:
f:id:lagrangian:20210128184053p:plain
Canvasをダブルクリックした後のSceneビュー
マウスのホイールで視点を近づけてOvarlay部分を拡大表示にします.次にHierarchyビューのScoreTextをクリックしてInspectorビューのRect TransformのWidthを300,Heightを60ぐらいにします.次にText Mesh Pro UGUI (Script)の中でFont StyleをBold(太字)のBをクリックし,Font Sizeを50,またAlignmentを図のように左寄せ縦位置中央寄せにします:
f:id:lagrangian:20210128185827p:plain
ScoreText設定
続いてフォントの色や縁取りを設定します.色や縁取りは直感的に設定できますのでここでは詳しく説明しませんが次のような設定にしました:
f:id:lagrangian:20210128191409p:plain
ScoreText設定その2
あとはこのテキストを画面右上の丁度良いところに配置します.Move Toolを選択し右上の丁度良い位置に移動します:
f:id:lagrangian:20210128191843p:plain
ScoreTextをMove Toolで移動する
この状態でPlayボタンを押してみます.いい感じです^^:
f:id:lagrangian:20210128192223p:plain
GameビューでのScoreTextの表示
ここでようやくスクリプトになります.今までの状態ではずっと"Score:"と表示されるだけで得点は加算されませんでした.そこでPaddleがCylinderをキャッチするたびに1点ずつ得点が加算されるスクリプトを作りましょう.ProjectビューのAssetsフォルダ内で右クリックして[Create]→[C# Script]を選択しできたファイルをTextControllerにリネームします.それからTextControllerをダブルクリックして次のコードを入力してください:

using UnityEngine;
using TMPro;

public class TextController : MonoBehaviour
{
    int score = 0;
    public TextMeshProUGUI scoreText;
    GameObject panel;
    
    public void AddScore()
    {
        this.score++;
    }
    // Start is called before the first frame update
    void Start()
    {
        panel = GameObject.Find("Panel");
        scoreText = panel.GetComponentInChildren<TextMeshProUGUI>();

    }

    // Update is called once per frame
    void Update()
    {
        scoreText.text = "Score:" + score.ToString();
    }
}

このスクリプトは開始時にPanelを探し,Panelの子要素のTextMeshProUGUIオブジェクトのScoreTextをscoreTextという名前で登録し,毎フレームごとに変数scoreの値を文字列"Score:"の後に表示させます.ただし,ここに登場するAddScoreメソッドをPaddleControllerから呼び出すまでは得点は0のままです.そこでPaddleControllerに次のようにPaddleにCylinderが衝突したらAddScoreで1点ずつ得点を加算するように書き換えましょう:

using UnityEngine;


public class PaddleController : MonoBehaviour
{
    public GameObject canvas;
    // Start is called before the first frame update
    void Start()
    {
        canvas = GameObject.Find("Canvas");
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKey(KeyCode.LeftArrow) && transform.position.x > -20f)
        {
            transform.Translate(-20 * Time.deltaTime, 0f, 0f, Space.World);
        }
        if (Input.GetKey(KeyCode.RightArrow) && transform.position.x < 20f)
        {
            transform.Translate(20 * Time.deltaTime, 0f, 0f, Space.World);
        }
        if (Input.GetKey(KeyCode.UpArrow) && transform.position.y < 15f)
        {
            transform.Translate(0f, 20 * Time.deltaTime, 0f, Space.World);
        }
        if (Input.GetKey(KeyCode.DownArrow) && transform.position.y > 2f)
        {
            transform.Translate(0f, -20 * Time.deltaTime, 0f, Space.World);
        }
    }
    private void OnTriggerEnter(Collider other)
    {
        canvas.GetComponent<TextController>().AddScore();
        Destroy(other.gameObject);

    }
}

今回追加したのは

        canvas.GetComponent<TextController>().AddScore();

の部分です.CanvasにアタッチされたスクリプトTextControllerのAddScoreメソッドを実行せよ,ということですね.これを実行したいがためにフィールドでpublic GameObject canvas;と宣言し,Startメソッド内でcanvas = GameObject.Find("Canvas");としてCanvasを探しています.

さて,スクリプトが完成したのでそれをアタッチします.まずTextControllerはCanvasにアタッチします.ProjectビューのAssetsフォルダの中からTextControllerをクリックし,HierarchyビューのCanvasにドロップします.次にCanvasが選択された状態で,左の三角のマークをクリックしその下のPanelを表示し,さらにその左の三角のマークをクリックしてその下のScoreTextを表示します.そしてScoreTextをそのままドラッグしてCanvasのInspectorビューのText Controller (Script)の中のScore Textにドロップします.このときHierarchyビューのScoreTextを不用意にクリックして選択状態にするとInspectorビューがScoreTextのものに変わってしまうので注意してください:

f:id:lagrangian:20210129092919p:plain
ScoreTextをTextControllerにアタッチする
以上でPaddleがCylinderに衝突したときにScore が1点ずつ加算されるようになりましたので,早速}Playボタンをクリックして実行してみます:

www.youtube.com

得点が加算されていることが分かります. なお,今回テキストを表示するために使用したText Mesh Proは標準では日本語に対応しておりません.日本語を表示する方法につきましてはまた別の機会にご紹介します.

次回はGAME OVER画面を作ります.


ゲーム制作ランキング

にほんブログ村 ゲームブログ ゲーム制作へ
にほんブログ村