【Unity入門】2Dアクションを作ろう【ゲームオーバー】

この記事は本のように順を追って解説しています。この記事は途中のページになります。
この記事を見ていて、現在の状況がわからない場合や忘れてしまった事などが出てきたら↓のリンクから目次ページへ飛べますので立ち戻って見てください。

<残機の加算・減算をしよう>

continue blink

さて、現在敵にやられたらコンティニューポイントまで戻るところまで実装しました。

とりあえず、今度は残機を増やしたり減らしたりする処理を実装しましょう。

クリックすると展開します
 using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GManager : MonoBehaviour
{
    public static GManager instance = null;

    public int score = 0;
    public int stageNum = 1;
    public int continueNum = 0;
    public int heartNum = 3;

    public bool isGameOver = false;

    private void Awake()
    {
        if(instance == null)
        {
            instance = this;
            DontDestroyOnLoad(this.gameObject);
        }
        else
        {
            Destroy(this.gameObject);
        }
    }
    
    /// <summary>
    /// 残機を1つ増やす
    /// </summary>
    public void AddHeartNum()
    {
        if(heartNum < 99)
        {
            ++heartNum;
        }
    }
    
    /// <summary>
    /// 残機を1つ減らす
    /// </summary>
    public void SubHeartNum()
    {
        if(heartNum > 0)
        {
            --heartNum;
        }
        else
        {
            isGameOver = true;
        }
    }
}

ゲームマネージャーに残機を増やしたり減らしたりする関数を追加しました。

単に減らしたり増やしたりすると無限に増えちゃったり、マイナスになってしまったりするのでこのように処理を追加します。

↓プレイヤー側も敵に当たったら残機をマイナスにする処理を入れましょう。

クリックすると展開します
     #region//接触判定
    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.collider.tag == enemyTag)
        {

            //踏みつけ判定になる高さ
            float stepOnHeight = (capcol.size.y * (stepOnRate / 100f));
            //踏みつけ判定のワールド座標
            float judgePos = transform.position.y - (capcol.size.y / 2f) + stepOnHeight;
            foreach (ContactPoint2D p in collision.contacts)
            {
                if (p.point.y < judgePos)
                {
                    ObjectCollision o = collision.gameObject.GetComponent<ObjectCollision>();
                    if (o != null)
                    {
                        otherJumpHeight = o.boundHeight;    //踏んづけたものから跳ねる高さを取得する
                        o.playerStepOn = true;        //踏んづけたものに対して踏んづけた事を通知する
                        isOtherJump = true;
                        isJump = false;
                        jumpTime = 0.0f;
                    }
                    else
                    {
                        Debug.Log("ObjectCollisionが付いてないよ!");
                    }
                }
                else
                {
                    anim.Play("player_down");
                    isDown = true;
                    GManager.instance.SubHeartNum(); //New!
                    break;
                }
            }
        }
    }
    #endregion

<ステージにやられ判定をつけよう>

さて、そろそろゲームオーバー画面を実装したいのですが、ゲームオーバーをテストするに当たっていちいち敵にぶつかっていくのはめんどくさいので先に落ちたらやられてしまうようにしましょう。

その前に、ステージコントローラーのプレイヤー位置を移動させる処理を関数化します。

クリックすると展開します
 using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class stageCtrl : MonoBehaviour
{

    [Header("プレイヤーゲームオブジェクト")]public GameObject playerObj;
    [Header("コンティニュー位置")]public GameObject[] continuePoint;

    private player p;
    void Start()
    {
        if (playerObj != null && continuePoint != null && continuePoint.Length > 0)
        {
            playerObj.transform.position = continuePoint[0].transform.position;
            p = playerObj.GetComponent<player>();
        }
    }

    /// <summary>
    /// プレイヤーをコンティニューポイントへ移動する
    /// </summary>
    public void PlayerSetContinuePoint()
    {
        playerObj.transform.position = continuePoint[GManager.instance.continueNum].transform.position;
        p.ContinuePlayer();
    }
    

    // Update is called once per frame
    void Update()
    {
        if (GManager.instance != null)
        {
            if (continuePoint.Length > GManager.instance.continueNum)
            {
                if (p.IsDownAnimEnd())
                {
                    PlayerSetContinuePoint();
                }
            }
        }
    }
}

これで外からプレイヤーの位置を元に戻せるようになりました。

そして今度はアイテムを作った時と同じような感じでやられ判定を作っていきます。

クリックすると展開します
 using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class deadPoint : MonoBehaviour
{
    [Header("ステージコントローラー")] public stageCtrl ctrl;

    private string playerTag = "Player";
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.tag == playerTag)
        {
            if (GManager.instance != null)
            {
                GManager.instance.SubHeartNum();
                if (!GManager.instance.isGameOver)
                {
                    ctrl.PlayerSetContinuePoint();
                }
            }
        }
    }
}

このスクリプトは範囲内にプレイヤーが入ってきた時、残機を1マイナスしてコンティニューポイントに戻すスクリプトです。

↓この緑の枠の中に入ったらやられた判定にしようと思います。

dead zone

インスペクターからステージコントローラーを設定するのを忘れずに。そしてBox Collider 2DにIsTringgerにチェックを入れます。

まだ仮の状態なので適当でOKです。この状態で再生すると

dead point return

適当に設置したため、中途半端なところで戻ってますが、いい感じにやられ判定を置く事ができました。

<ゲームオーバー画面を作ろう>

残機がマイナスになってしまったらゲームオーバーにしたいと思います。

まずは真っ黒な画像を用意します。

black

Imageを設置し、WidthとHeightを解像度に合わせて、↑の画像をスプライトにして突っ込みます

screen black out

Colorのアルファ値を下げてあげるとちょっと薄暗い感じにする事ができます。

そして、Textとボタンを置いてゲームオーバーっぽくすればOKです。まぁ、下書きですので適当でOKです。

Textは相変わらずfontSizeに気をつけてください。極力他のテキストと同じ大きさをしようしましょう。

game over

UGUIを置く順番には注意しましょう。

canvas hierarchy

下にある方が手前に表示されるのでFadeが一番下になるようにします。

次にゲームオーバーなのですが、ゲームオーバーに関連するUIは全部最初においた薄いグレーアウトの子オブジェクトにしてしまうといいと思います。

こうする事で親をSetActiveでオンオフすることによってゲームオーバーを簡単に画面に表示する事ができるようになります。

<ゲームオーバー画面をスクリプトから表示しよう>

ゲームオーバーになってしまったら最初のステージに戻るようにしようと思います。

まずは、ゲームオーバー画面を表示する為にゲームマネージャーに最初から始めるの処理を書きましょう。

ゲームマネージャーに↓の変数を追加します。これはデフォルトでの残機の数です。

public int defaultHeartNum = 3;

最初から始める時の処理を書きます。

     /// <summary>
     /// 最初から始める時の処理
     /// </summary>
     public void RetryGame()
     {
         isGameOver = false;
         heartNum = defaultHeartNum;
         score = 0; 
         stageNum = 1;
         continueNum = 0; 
     }

フラグを下ろしてあげて、残機をデフォルトのものに戻しましょう。スコアも0に戻してあげます。

ステージコントローラーを以下のように変えます。

クリックすると展開します
 using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class stageCtrl : MonoBehaviour
{

    [Header("プレイヤーゲームオブジェクト")]public GameObject playerObj;
    [Header("コンティニュー位置")]public GameObject[] continuePoint;
    [Header("ゲームオーバー")]public GameObject GameOverObj;
    [Header("フェード")]public FadeImage fade;
    
    private player p;
    private int nextStageNum;
    private bool startFade = false;
    
    void Start()
    {
        //プレイヤーをスタート位置に
        if (playerObj != null && continuePoint != null && continuePoint.Length > 0)
        {
            playerObj.transform.position = continuePoint[0].transform.position;
            p = playerObj.GetComponent<player>();
        }
        
        //ゲームオーバーのオブジェクトを非表示に
        if(GameOverObj != null)
        {
            GameOverObj.SetActive(false);
        }
    }

    /// <summary>
    /// プレイヤーをコンティニューポイントへ移動する
    /// </summary>
    public void PlayerSetContinuePoint()
    {
        playerObj.transform.position = continuePoint[GManager.instance.continueNum].transform.position;
        p.ContinuePlayer();
    }
    
    /// <summary>
    /// 最初から始める
    /// </summary>
    public void Retry()
    {
        GManager.instance.RetryGame();
        
        ChangeScene(1);
    }
    
    /// <summary>
    /// ステージを切り替えます。
    /// </summary>
    /// <param name="num">Number.</param>
    public void ChangeScene(int num)
    {
        if (fade != null)
        {
            nextStageNum = num;
            fade.StartFadeOut();
            startFade = true;
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (GManager.instance != null)
        {
            //ゲームオーバー
            if (GManager.instance.isGameOver)
            {
                GameOverObj.SetActive(true);
            }
            //コンティニュー
            else if (continuePoint.Length > GManager.instance.continueNum)
            {
                if (p.IsDownAnimEnd())
                {
                    PlayerSetContinuePoint();
                }
            }
        }

        //ステージを切り替える
        if (fade != null && startFade)
        {
            if (fade.compFadeOut)
            {
                GManager.instance.stageNum = nextStageNum;
                SceneManager.LoadScene("stage" + nextStageNum);
            }
        }
    }
}

ゲームオーバーのオブジェクトをSetActiveでコントロールし、ゲームオーバーになったら出現するようにします。

ゲームオーバーになってしまったら最初のステージに戻りたいですが、クリアーしたら次のステージに進みたいので↓のように番号でステージ移動ができるようにしています。

     /// <summary>
     /// ステージを切り替えます。
     /// </summary>
     /// <param name="num">Number.</param>
     public void ChangeScene(int num)
     {
         if (fade != null)
         {
             nextStageNum = num;
             fade.StartFadeOut();
             startFade = true;
         }
     }

ゲームオーバーでRetryボタンを押した時は↓の最初から始める関数を呼んであげればOKです。

     /// <summary>
     /// 最初から始める
     /// </summary>
     public void Retry()
     {
         GManager.instance.RetryGame();
         
         ChangeScene(1);
     }

ステージ1にシーンチェンジしようとしているので結果、最初に戻ることができます。

現在のステージがステージ1だった場合ちょっと無駄な処理のように思えますが、シーンをロードし直すことによって状況が元に戻る為安全です。

ロードし直さないと敵が消えたままになっていたり、アイテムが消えたままになってしまうのでシーンをロードし直すといいと思います。

各種インスペクターでの設定を忘れずに。

stage control inspector game over fade

↓ボタンを押したらStageCtrlのRetryの関数を呼ぶようにしましょう。

この状態で再生すると

retry game

これでゲームオーバーを作成する事ができました。

<わからない事、質問等があれば>

このサイトの説明ではよくわからなかったとか、もっと知りたい事などがあれば

自分の Youtubeの動画にコメントで質問していただければ動画でお答えしようと思います。

文章同士のやり取りだと伝わりづらいし、ラリーに時間がかかりそうなので動画で回答します。

↓の動画が回答の一例になります。どの動画でもいいのでご遠慮なくコメントしてください

できたらチャンネル登録よろしくお願いします!



タイトルとURLをコピーしました