【Unity入門⑨】HPが0になったらゲームオーバーの演出をさせよう

Unity2D入門シリーズ

前回の記事で、敵に触れたらダメージを食らうHPバーを作りました。
今回はプレイヤーのHPが0になったらゲームオーバになるUIを作ってみましょう!

この記事では、
プレイヤーのHPが0になったら画面に「GAME OVER」、「リトライ」ボタンを表示させる
・「リトライ」ボタン押したら初期位置にリスポーンする

のような仕組みを解説していきます!

完成イメージ

  • 画面中央に「GAME OVER」+「リトライ」ボタンを表示
  • リトライボタンを押すとシーンを再読み込みして最初からスタートできる

① UI を用意する(Canvas)

ゲームオーバーになった場合に表示させるUI(テキスト、ボタン)を作っていきましょう!

  1. Canvas を作成
    • Hierarchy → 右クリック → UI > Canvas
    • Render Mode:Screen Space – Overlay(そのままでOK)
    • ※自動で EventSystem も作られます(なければ UI > Event System を追加)
  2. 全画面の暗幕を作る
    • Canvas を右クリック → UI > Panel(名前:GameOverPanelにする)
    • Image の色を 黒 (0,0,0)Alpha=160/255 くらい(薄暗く)
    • Inactive(非アクティブ) にしておく(起動直後に見えないように)
  3. ゲームオーバー時のテキスト & リトライボタン
    • GameOverPanel の子に UI > Text (TMP)UI > Text(名前:Title
      • 文字:GAME OVER
    • GameOverPanel の子に UI > Button(名前:RetryButton、ラベル:RETRY
      👉「RETRY」ボタンを押したときに シーンを再読み込み(ゲーム再スタート) するため用のボタンです

<3.ゲームオーバー時のテキスト
テキストのサイズ、位置などを調整します。

<3.リトライボタン
ボタンの位置はPos X、Pos Yで調整します。


② MainManager.csの新規作成

ゲームオーバー時のUI表示、リトライをまとめて管理するMainManager.csを新規作成します📝(コピペOK)

using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using System.Collections;

public class MainManager : MonoBehaviour
{
    [Header("UI 参照")]
    [SerializeField] private GameObject _gameOverPanel;   // ← GameOverPanel を割り当て
    [SerializeField] private Button _retryButton;         // ← RetryButton を割り当て

    private bool _shown = false;

    private void Awake()
    {
        // 起動直後は非表示
        if (_gameOverPanel != null) _gameOverPanel.SetActive(false);

        if (_retryButton != null)
            _retryButton.onClick.AddListener(Restart);
    }

    // 外部(Player)から呼ぶ
    public void Show()
    {
        if (_shown) return;
        _shown = true;

        // パネルを出す
        if (_gameOverPanel != null) _gameOverPanel.SetActive(true);

        // 時間停止(UI演出は unscaledDeltaTime で動かす)
        Time.timeScale = 0f;

    }

    public void Restart()
    {
        // 時間を戻してからリロード
        Time.timeScale = 1f;
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
    }
}

③各処理の説明

UI参照の変数

[SerializeField] private GameObject _gameOverPanel;
[SerializeField] private Button _retryButton;
  • UnityのInspectorから
    • ゲームオーバー用のPanel
    • Retryボタン
      紐づけるための変数です。
  • Unity上の設定から設定できるようにする

ゲームオーバーの多重実行防止

private bool _shown = false;
  • ゲームオーバー処理が
    何回も呼ばれてしまうのを防ぐためのフラグです。

落下判定は Update() で毎フレーム実行されるため、
何もしないと 何度もゲームオーバー処理が走る可能性があります。


Awake() の役割

private void Awake()
{
    if (_gameOverPanel != null)
        _gameOverPanel.SetActive(false);

    if (_retryButton != null)
        _retryButton.onClick.AddListener(Restart);
}

Awake とは?

  • オブジェクトが生成された直後に1回だけ呼ばれる
  • 「初期設定」を書くのに向いている

_gameOverPanel.SetActive(false);

GameOverPanel を非表示にする設定をしています。
ゲーム開始直後からゲームオーバー画面が表示されないようにするためです。


_retryButton.onClick.AddListener(Restart);

Retryボタンに処理を登録しています。
Retryボタンが押されたらRestart() メソッドを実行するという 予約をしています。

※ ボタンを押すたびに処理を追加しないため、Awakeで1回だけ登録するのがポイントです。


Show() メソッド(ゲームオーバーにさせる)

public void Show()
  • 「ゲームオーバーになった瞬間」に呼ばれる
  • Player や他のクラスから呼び出す用

if (_shown) return;
_shown = true;
  • 落下中は毎フレーム条件を満たす
  • そのたびに呼ばれると不具合の原因になる

➡️「最初の1回だけ実行する」ための安全装置です(2重実行を防止)


_gameOverPanel.SetActive(true);

GameOver UI を表示させるということをしています。

  • 非表示だったUIを表示する


Restart()(リトライボタンを押したとき)

public void Restart()
{
    Time.timeScale = 1f; // 時間を元に戻す
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); // 同じシーンを再読み込み
}

「RETRY」ボタンを押したときに呼ばれます。

  • Time.timeScale = 1
    → ゲームを再開できるように時間を元通りにする
  • SceneManager.LoadScene()
    → 今のシーンをリロードして最初からスタート!

これで「やり直し」ができるようになります。


④MainManagerのセットアップ

②で作成したスクリプトを管理する用のMainManagerオブジェクトを作成します。

  1. MainManagerオブジェクトを作成する
    • Hierarchy → +ボタンクリック →「create Empty」で空のオブジェクトを作成する
    • 名前を「MainManager」に変更
      create Emptyはスクリプトだけ入れたい時などに使用されます)
  2. MainManager.csの適用
    • Add Component> MainManager.csを選択して適用する
  3. UIのセットアップ
    • 「gameOverPanel」 に CanvasのGameOverPanel をドラッグする
    • 「retryButton」 に CanvasのRetryButton をドラッグする

⑤Player からゲームオーバーを呼ぶ処理を書く

Player.csにMainManager.csで追加した処理を呼び出します。
HP処理の _TakeDamage() 0 以下になった瞬間に Show() を呼びます。

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.InputSystem;

public class Player : MonoBehaviour
{
    [SerializeField, Header("最大HP")]
    private int _maxHP = 5;

    private int _currentHP;
    [SerializeField, Header("HPバーのImage")]
    private Image _hpBarFill;

    private MainManager _mainManager; // 追加
    private PlayerInput _input; // 追加

    void Start()
    {
        _currentHP = _maxHP;
        _UpdateHPBar();
        _mainManager = FindObjectOfType<MainManager>(); // 追加
        _input = GetComponent<PlayerInput>(); // 追加
    }

    private void OnCollisionEnter2D(Collision2D col)
    {
        if (col.collider.CompareTag("Enemy"))
        {
            _TakeDamage(1);
        }
    }

    // ダメージ処理
    private void _TakeDamage(int damage)
    {
        _currentHP -= damage;
        _currentHP = Mathf.Clamp(_currentHP, 0, _maxHP);

        _UpdateHPBar();

        if (_currentHP <= 0) // 追加
        {
            // 操作を止める
            if (_input != null) _input.enabled = false;

            // ゲームオーバーを表示
            if (_mainManager != null) _mainManager.Show();
        }
    }

    // HPバーの見た目を更新
    private void _UpdateHPBar()
    {
        if (_hpBarFill != null)
        {
            _hpBarFill.fillAmount = (float)_currentHP / _maxHP;
        }
    }
}

全体の流れをまとめると…

手順処理担当関数
ゲーム開始パネル非表示、ボタン登録Awake()
HP0になるパネルを表示、時間停止Show()
RETRY押下時間再開、シーン再読み込みRestart()


動作確認

  1. GameOverPanel を非アクティブにしておく(Startで有効化されないように)
  2. プレイして敵に触れ、HPを0にする
  3. 画面が暗転+GAME OVER、操作が止まり、RETRYでシーン再読み込み

👉HPが0になったらゲームオーバーUIを表示させ、リトライボタンでリスポーンすることが出来ました!!


まとめ

処理名内容
Awake()最初にUIを非表示にして、Retryボタンの動作を登録
Show()ゲームオーバー画面を出して、時間を止める
Restart()時間を戻してシーンを再読み込み(リトライ)
  • GameOverPanel を用意して MainManager で表示・停止・再開を管理
  • Player 側は HPが0の瞬間だけ Show() を呼ぶ

敵からダメージを食らうようにしましたが、このままだと敵を倒す処理が実装されていないので次回では倒せるようにします!

コメント

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