【Unity 2Dローグライク】公式チュートリアルをやってみる part.13~UIを作る
こんにちは!ヤギです!
Unityの2Dローグライクの
公式チュートリアルをやってみる part.13になります!
※前回(part.12)の記事はこちら
www.yagigame.com
記事概要
今回の記事では、食料を表示するUIやレベルの管理についてご説明していきます。※part.13に対応する公式チュートリアルの章は、Enemy Animator Controllerです!
unity3d.com
※この記事は、ひよこのたまご様の記事をリスペクトしています。
hiyotama.hatenablog.com
UIの作成
まず初めに、背景から作成していきます。1. GameObject > UI > Canvasをクリックし、UIを表示する空間を作成します。
2. GameObject > UI > Imageをクリックし、背景を表示する空間を作成します。
※Canvasの子として作成されます。
※Scene viewからCanvasとimageを確認すると、Canvasの一部にimageがあります。
3. imageのAnchorをクリックし、option(またはalt)を押しながら、右下の広げるマークをクリックします。
※これでCanvas全体に、imageが広がります。
4. Colorをクリックし、色を黒色に変更します。
5. imageの名前をLevelImageとします。
6. GameObject > UI > Textをクリックし、レベルを表示する空間を作成します。
※名前をLevelTextとします
7. LevelTextのInspectorから以下の内容の修正を行います。
・Font Size を32にする。
・FontをPressStart2Pに変更する。
・Colorを白にする。
・Horizon OverflowとVectical OverflowをOverflowにする。
・Alignmentを真ん中にする。
・TextをDay 1とする。
※これを行うと、次の画面のようになります!
8. Hierarchy上で、LevelTextをLevelImageの文字の上にドラッグします。
※これで、LevelTextがLevelImageの子になります。
9. GameObject > UI > Textをクリックし、食料を表示する空間を作成します。
※名前をFoodTextとします。
10. Anchorをクリックし、option(またはalt)を押しながら画面中央の下をクリックします。
11. FoodTextのInspectorから以下の内容の修正を行います。
・Font Size を24にする。
・FontをPressStart2Pに変更する。
・Colorを白にする。
・Horizon OverflowとVectical OverflowをOverflowにする。
・Alignmentを真ん中にする。
・TextをFood: 100とする。
・Anchor > Max > Y を0.05にする。
・Anchor > Min > Y を0.05にする。
・Pos Yを0にする。
※これで、画面下に食料が表示されます。
12. Hierarchy上で、FoodTextをCanvasの直下にドラッグします。
※これで、FoodTextがCanvasの子になります。Canvasの下の方にあるオブジェクトから優先されるため、FoodTextが表示されなくなります。
※一通りUIが完成しました。次にUIを制御するスクリプトを作成していきます。
UIを制御するスクリプト(レベルの表示)の作成
1. GameManager.csを開き、スクリプトにUIを制御する部分を追加していきます。※GameManage.csにはレベル(Day)の表示を制御する部分を追加していきます。
※ソース内に解説を記載しました。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; //part.13で追加 UIを使うために必要 public class GameManager : MonoBehaviour { //ここからpart.13で追加 public float levelStartDelay = 2f; //レベルスタート時の時間間隔 private Text levelText; //レベルを表示するテキスト private GameObject levelImage; //UIの表示領域 表示のオンオフを切り替える private bool doingSetup; //設定中かどうかのフラグ //ここまでpart.13で追加 //ここからpart.12で追加 public float turnDelay = .1f; //1ターンの時間 private List<Enemy> enemies; //複数の敵を管理 private bool enemiesMoving; //敵の移動フラグ //ここまでpart.12で追加 //クラスに属し、複数のシーンで使われる変数を宣言 //Staticにすることで、他のスクリプトからも呼び出すことができます public static GameManager instance = null; //ここから:part.10で追加 public int playerFoodPoints = 100; //プレイヤーの食料 //HideInspectorをつけることで、Inspector viewに表示されなくなる [HideInInspector] public bool playerTurn = true; //プレイヤーのターンかの判定フラグ //ここまで:part.10で追加 //BoardManager型の変数を宣言 private BoardManager boardScript; //テストとして、敵が出現するレベルの3とする //part.13で1に修正 private int level = 1; // AwakeはStartよりも前、最初に呼ばれる void Awake() { //GameManagerが存在しなければ、このオブジェクトを設定する if (instance == null) instance = this; else if (instance != this) //すでに存在する場合、このオブジェクトは不要なため破壊する Destroy(gameObject); //シーン遷移時に、このオブジェクトは破壊せず引き継ぐ DontDestroyOnLoad(gameObject); //ここからpart.12で追加 enemies = new List<Enemy>(); //敵を初期化 //ここまでpart.12で追加 //BoardManagerのコンポーネントを取得 boardScript = GetComponent<BoardManager>(); //ステージ生成の関数を呼ぶための、関数を呼ぶ InitGame(); } //ここからpart.13で追加 //シーンが飛び出されたタイミングで実行される [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] static public void CallbackInitialization() { //register the callback to be called everytime the scene is loaded SceneManager.sceneLoaded += OnSceneLoaded; } //シーンが呼び出されたタイミングで初期化する static private void OnSceneLoaded(Scene arg0, LoadSceneMode arg1) { instance.level++; instance.InitGame(); } //ここまでpart.13で追加 void InitGame() { //ここからpart.13で追加 //設定中フラグをオンにする doingSetup = true; //levelImageにUIを設定する levelImage = GameObject.Find("LevelImage"); //levelTextにUIのテキストを取得し設定する levelText = GameObject.Find("LevelText").GetComponent<Text>(); //levelTextにゲーム内のlevelを設定する levelText.text = "Day " + level; //UIを表示する levelImage.SetActive(true); //2秒後にUIを非表示にする Invoke("HideLevelImage", levelStartDelay); //ここまでpart.13で追加 //ここからpart.12で追加 enemies.Clear(); //ステージ移動時は敵をリセットする //ここまでpart.12で追加 //ステージ生成の関数を呼ぶ boardScript.SetupScene(level); } //ここからpart.13で追加 //UIを非表示にする private void HideLevelImage() { levelImage.SetActive(false); doingSetup = false; } //ここまでpart.13で追加 //ここまでpart.10で追加 //ここからpart.12で追加 void Update() { //プレイヤーのターンか、敵の動いている場合は、アップデートしない //part.13でdoigSetupを追加 if (playerTurn || enemiesMoving ||doingSetup) return; //敵の動いていない、敵のターンのみ敵を動かす StartCoroutine(MoveEnemies()); } //敵をリストに加える処理 public void AddEnemyList(Enemy script){ enemies.Add(script); } //敵を移動させる処理 IEnumerator MoveEnemies() { //エネミー移動フラグをtrueにする enemiesMoving = true; //1ターン待つ yield return new WaitForSeconds(turnDelay); //敵がいなければ if (enemies.Count == 0) { //1ターン待つ yield return new WaitForSeconds(turnDelay); } //敵の数だけ、敵を移動させる for (int i = 0; i < enemies.Count; i++) { enemies[i].MoveEnemy(); //1ターン待つ yield return new WaitForSeconds(turnDelay); } //プレイヤーのターンにする playerTurn = true; enemiesMoving = false; } //ここまでpart.12で追加 //ここかpart.10で追加 public void GameOver() { //ここからpart.13で追加 //ゲームオーバー時のテキストを設定 levelText.text = "After " + level + " days, you starved."; //UIを表示 levelImage.SetActive(true); //enabledをfalseにすることで、GameManagerが無効になる enabled = false; } }
※これで、Day 1などが表示されるようになりました!
UIを制御するスクリプト(食料の表示)の作成
1. Player.csを開き、スクリプトにUIを制御する部分を追加していきます。※Player.csには食料(Food)の表示を制御する部分を追加していきます。
※ソースの中の解説をご参照ください!
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; //シーンの読み込みに必要 using UnityEngine.UI; //part.13で追加 //MovingObjectクラスを継承する public class Player : MovingObject { //ここからpart.13で追加 public Text foodText; //食料を表示するテキスト //ここまでpart.13で追加 public int wallDamage = 1; //壁へのダメージ量 public int pointsPerFood = 10; //食べ物の回復量 public int pointsPerSoda = 20; //ソーダの回復量 public float restartLevelDeray = 1f; //ステージ移動時の時間 private Animator animator; //アニメーション用変数 private int food; //食料 // Use this for initialization //MovingObjectクラスのStartを継承する protected override void Start () { //animatorのコンポーネントを設定 animator = GetComponent<Animator>(); //foodをステージ間で引き継げるように、GameManagerから設定 food = GameManager.instance.playerFoodPoints; //ここからpart.13で追加 //foodTextを初期化 foodText.text = "Food: " + food; //ここまでpart.13で追加 //GameObjectのStartを呼び出す base.Start(); } //PlayerのfoodをGameManageに保存する public void OnDisable() { GameManager.instance.playerFoodPoints = food; } protected override void AttemptMove<T>(int xDir, int yDir) { //移動するたびに食料が減る food--; //ここからpart.13で追加 //減らした食料をUIに表示する foodText.text = "Food: " + food; //ここまでpart.13で追加 //MovingObjectのAttemptMoveを呼び出す base.AttemptMove<T>(xDir, yDir); RaycastHit2D hit; //ゲームオーバーか確認 CheckIfGameOver(); //プレイヤーのターン終了 GameManager.instance.playerTurn = false; } //プレイヤーが壁にぶつかった場合、壁をチョップする protected override void OnCantMove<T>(T component) { //Wallスクリプトを使えるように設定 Wall hitWall = component as Wall; //壁にダメージを与える hitWall.DamageWall(wallDamage); //チョップするアニメーションを呼び出す animator.SetTrigger("PlayerChop"); } //プレイヤーが、Exit、Food、Sodaと接触した場合に呼び出す private void OnTriggerEnter2D(Collider2D other) { //Exitと接触した場合 if(other.tag == "Exit"){ //ステージ移動の時間分待ってから、次のツテージに移動する Invoke("Restart", restartLevelDeray); enabled = false; }else if(other.tag == "Food"){ //食料と接触した場合 //食料を回復 food += pointsPerFood; //ここからpart.13で追加 //増えた食料をUIに表示する foodText.text = "+"+pointsPerFood+" Food: " + food; //ここまでpart.13で追加 //食料を削除 other.gameObject.SetActive(false); }else if(other.tag == "Soda"){ //食料を回復 food += pointsPerSoda; //ここからpart.13で追加 //増えた食料をUIに表示する foodText.text = "+" + pointsPerFood + " Food: " + food; //ここまでpart.13で追加 //ソーダを削除 other.gameObject.SetActive(false); } } //プレイヤーがExitに到達した場合、次のステージを呼び出す private void Restart(){ //シーンを呼び直す SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex,LoadSceneMode.Single); } //プレイヤーが敵に攻撃された場合、食料を減らす public void LoseFood(int loss){ //攻撃を受けたアニメーションを呼び出す animator.SetTrigger("PlayerHit"); //食料を減らす food -= loss; //ここからpart.13で追加 //減らした食料をUIに表示する foodText.text = "-" + loss+ " Food: " + food; //ここまでpart.13で追加 //ゲームオーバーか判定 CheckIfGameOver(); } // Update is called once per frame void Update () { //プレイヤーのターンではない場合、何も実行しない if (!GameManager.instance.playerTurn) { return; } //左右の移動 int horizontal = 0; //上下の移動 int vertical = 0; //左右の移動量を受け取る horizontal = (int)Input.GetAxisRaw("Horizontal"); //上下の移動量を受け取る vertical = (int)Input.GetAxisRaw("Vertical"); //上下左右のいずれかに移動を制限する if(horizontal != 0){ vertical = 0; } //左右上下のいずれかに移動する場合 if(horizontal != 0 || vertical != 0){ //プレイヤーの侵攻方向に壁があるか確認 AttemptMove<Wall>(horizontal, vertical); } } //食料が0いかになった場合、ゲームオーバーにする private void CheckIfGameOver(){ if(food <= 0){ //GameManagerのGameOverを呼び出す GameManager.instance.GameOver(); } } }
2. Hierarchy view > PlayerのInspector内の Player Script > FoodTextに、Canvas > FoodTextをドラッグして設定します。
※これで、ゲーム内で食料が表示されるようになります。
ゲームを実行してみよう!
ゲームを実行してみましょう!プレイヤーが移動すると、食料が減り、Exitにたどり着くと、ステージが遷移することができると思います!
次回予告
次回の記事では、ゲーム内の効果音などサウンドについて書いていきたいと思います。※次回の記事はこちら
www.yagigame.com
※Unityのチュートリアルの章としては、次回は(Audio and Sound Manager)となります!
読んでいただきありがとうございました!