前回はPaddleがCylinderをキャッチするとScoreが加算されるようにしました.今回はPaddleが3回Cylinderをキャッチし損ねるとGAME OVERの表示が出るようにしたいと思います.
まずGAME OVERの表示をするPanelを作成します.HierarchyビューのCanvasを右クリックして[UI]→[Panel]を選択します.Canvasの下にもう一つのPanelであるPanel (1)ができますのでそれをGameOverPanelにリネームしましょう:
HierarchyビューでGameOverTextが選択された状態でInspectorからRect TransformのWidthとHeightをそれぞれ800,200に変えます.続いてText Mesh Pro UGUI (Script)の中のTextの項目の中の"New Text"と表示されたところを"Game Over"に書き換え,Font Styleを太字(Bold),Font Sizeを130,Alignmentを上下左右ともに中央寄せにします:
今回はScoreTextと同じfont Assetを使用しますが,もちろん変えても構いません.注意してほしいのは同じfont Assetを使用している場合,fontの見た目(FaceやOutlineなど)を片方で変えるともう片方も共通なので同じように変わってしまうという点です.同じfont Assetを使用しているのだから当然ですね.さて,今回,Game Overの表示の下にReplayボタンを配置したいのでSceneビューで"Game Over"のテキストを少し上にずらしておきましょう.大体この辺にします:
HierarchyビューでButtonをクリックし,InspectorビューのButton (Script)のNormal Colorを変えます.ここでは緑色に変えてみます.またHierarchyビューでGameOverPanelをクリックしてInspectorビューのImage (Script)のColorをやはり緑色にして,Alpha値を100にします.出来上がったGame Over画面はこんな感じです:
using UnityEngine; using TMPro; public class TextController : MonoBehaviour { int score = 0; public TextMeshProUGUI scoreText; GameObject panel; int lose = 0; public void AddScore() { this.score++; } public int AddLose() { this.lose++; return lose; } // 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(); } }
このスクリプトではメソッドAddLoseだけが定義されてます.また,AddLoseはほかのスクリプトで利用できるよう戻り値としてloseを返しています.次に画面外にCylinderが出てしまったときにAddLoseを実行するためにCylinderControllerに次のように記述します:
using UnityEngine; public class CylinderController : MonoBehaviour { float speed; float rotx; float roty; float rotz; float rndx; float rndy; float rndz; public GameObject canvas; public GameObject paddle; public Transform gameoverPanel; // Start is called before the first frame update void Start() { speed = Random.Range(20f, 50f) * Time.deltaTime; rotx = 0; roty = 0; rotz = 0; rndx = Random.Range(-500f, 500f) * Time.deltaTime; rndy = Random.Range(-500f, 500f) * Time.deltaTime; rndz = Random.Range(-500f, 500f) * Time.deltaTime; } // Update is called once per frame void Update() { rotx += rndx; roty += rndy; rotz += rndz; transform.rotation = Quaternion.Euler(rotx, roty, rotz); transform.Translate(0f, 0f, -speed, Space.World); if (transform.position.z < -25) { canvas = GameObject.Find("Canvas"); int lose = canvas.GetComponent<TextController>().AddLose(); if (lose == 3) { gameoverPanel = canvas.transform.Find("GameOverPanel"); gameoverPanel.gameObject.SetActive(true); paddle = GameObject.Find("Paddle"); Destroy(paddle); } Destroy(gameObject); } } }
このコードはCylinderが画面外に出たら(z < -25),TextControllerのAddLoseを実行してloseを1増やし,loseが3になったらGameOverPanelを表示してpaddleを消滅させるというものです.一点注意すべきなのが,gameoverPanelをGameObjectのクラスではなくTransformのクラスにしている点です.というのもデフォルトではGameOverPanelは非表示つまりSetActiveがfalseになっているのですが,SetActiveがfalseのGameObjectはGameObject.Findメソッドで見つけることができないのでtransform.Findを使用しなければならないからです.またtransform.Findは親オブジェクトを指定したときに子オブジェクトを見つけるものなので親オブジェクトも先に見つけておかなくてはなりません.このため,上記コードのようにスクリプトを記述します.
これでReplayボタン以外ができました.次にReplayボタンのスクリプトを作成します. ProjectビューのAssetsフォルダ内で右クリックして[Create]→[C# Script]を選択し,できたファイルの名前をReplayScriptとして保存し,ダブルクリックして次のコードを入力します:
using UnityEngine; using UnityEngine.SceneManagement; public class ReplayScript : MonoBehaviour { public void OnClick() { SceneManager.LoadScene(0); } }
このスクリプトはReplayボタンが押されたときに最初(Scene番号0)のSceneを読み込みするというものです.今回のゲームでは一つしかSceneがありませんが,こうすることで,再度Sceneを読み込んで初期化することができます.なお,Scene番号の代わりに"MainScene"などとSceneの名前を入れても大丈夫です.このスクリプトをCtrl + sで保存したら,Unityに戻ります.ProjectビューのAssetsフォルダ内のReplayScriptをHierarcvhyビューのButtonまでドラッグしてドロップします.次にButtonのInspectorビューでButton (Script)のOn Click ()のList is Emptyの下の+マークをクリックします: