前回までで敵やコインを作ったので、これでゲームをクリアしたりゲームオーバーになったりする要素がそろいました。
そこで、ここからはステージクリア処理とゲームオーバー処理を作っていきます。主な作業内容は次の2つです。
- GameManager等のスクリプトの変更
- クリア・ゲームオーバー画面用のキャンバスの作成
まず、ここではGameManager等のいくつかのスクリプトを変更していきましょう。色々変更箇所があってややこしいので、注意しながら作業を進めてください。
GameManagerの変更
はじめにGameManagerスクリプトを変更します。GameManager.csを次のように書き換えてください(※変更箇所が多いので全文を載せます)。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; //追加
[RequireComponent(typeof(MoveSceneManager))]
[RequireComponent(typeof(SaveManager))]
[RequireComponent(typeof(SoundManager))]
[DefaultExecutionOrder(-5)]
public class GameManager : SingletonMonoBehaviour<GameManager>
{
[Header("シーンロード時に自動生成するプレハブを登録")]
[SerializeField]
GameObject[] prefabs = null;
//追加
[Header("UIの設定")]
[SerializeField]
GameObject clearCanvasPrefab = null;
[SerializeField]
GameObject gameOverCanvasPrefab = null;
[SerializeField]
string nextButtonName = "NextButton";
[SerializeField]
string retryButtonName = "RetryButton";
[SerializeField]
string titleButtonName = "TitleButton";
MoveSceneManager moveSceneManager;
SaveManager saveManager;
SoundManager soundManager;
//追加
bool isClear = false;
bool isGameOver = false;
int numOfCoins = 0;
int correctedCoins = 0;
public int CorrectedCoins
{
set
{
correctedCoins = value;
if(correctedCoins >= numOfCoins)
{
Clear();
}
}
get
{
return correctedCoins;
}
}
protected override void Awake()
{
base.Awake();
if (Debug.isDebugBuild)
{
}
moveSceneManager = GetComponent<MoveSceneManager>();
saveManager = GetComponent<SaveManager>();
soundManager = GetComponent<SoundManager>();
}
void Start()
{
if (Debug.isDebugBuild)
{
InstantiateWhenLoadScene();
InitGame(); //追加
}
}
void Update()
{
}
public void InstantiateWhenLoadScene()
{
if(moveSceneManager.SceneName == "Title")
{
return;
}
foreach (GameObject prefab in prefabs)
{
Instantiate(prefab, transform.position, Quaternion.identity);
}
}
//--ここから追加--
//ゲーム初期化メソッド
public void InitGame()
{
isClear = false;
isGameOver = false;
numOfCoins = GameObject.FindGameObjectsWithTag("Coin").Length;
correctedCoins = 0;
}
public void Clear()
{
if (isClear || isGameOver)
{
return;
}
isClear = true;
GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>().isActive = false;
//クリア画面のキャンバスを生成
Instantiate(clearCanvasPrefab, transform.position, Quaternion.identity);
//ボタンのコンポーネントを取得
Button nextButton = GameObject.Find(nextButtonName).GetComponent<Button>();
Button titleButton = GameObject.Find(titleButtonName).GetComponent<Button>();
//ボタンに、クリックしたときの処理を登録
//ただし「次のステージ」ボタンは次のステージがないときは押せないようにする
if(moveSceneManager.CurrentSceneNum < moveSceneManager.NumOfScene - 1)
{
nextButton.onClick.AddListener(() => moveSceneManager.MoveToScene(moveSceneManager.CurrentSceneNum + 1));
}
else
{
nextButton.interactable = false;
}
titleButton.onClick.AddListener(() => moveSceneManager.MoveToScene(0)); //タイトル画面に戻るので、シーン番号は0番
}
public void GameOver()
{
if (isGameOver || isClear)
{
return;
}
isGameOver = true;
GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>().isActive = false;
//ゲームオーバー画面のキャンバスを生成
Instantiate(gameOverCanvasPrefab, transform.position, Quaternion.identity);
//ボタンのコンポーネントを取得
Button retryButton = GameObject.Find(retryButtonName).GetComponent<Button>();
Button titleButton = GameObject.Find(titleButtonName).GetComponent<Button>();
//ボタンに、クリックしたときの処理を登録
retryButton.onClick.AddListener(() => moveSceneManager.MoveToScene(moveSceneManager.CurrentSceneNum)); //リトライなので、今と同じシーンを再読み込み
titleButton.onClick.AddListener(() => moveSceneManager.MoveToScene(0)); //タイトル画面に戻るので、シーン番号は0番
}
}
変更内容はコメントを読んで頂ければわかると思いますが、大まかにいうと
- 変数の初期化メソッドの追加
- クリア・ゲームオーバー処理用のメソッドの追加
- (ついでに)コインの枚数に関係する変数の追加
を行っています。
ちなみにクリア・ゲームオーバー処理用メソッドでは、キャンバス(※次回作ります)を生成してその中のボタンを検索し、そのボタンにメソッドを登録する、といった処理をしています。
MoveSceneManagerの変更
次に、シーンの読み込みを担当しているMoveSceneManagerのスクリプトを少しだけ変更します。「OnSceneLoaded」というメソッドを次のように変更してください。
//省略
//シーンのロード時に実行(最初は実行されない)
protected virtual void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
gameManager.InstantiateWhenLoadScene();
gameManager.InitGame(); //追加
}
//省略
シーンのロード時にGameManagerのいくつかの変数を初期化したいので、このような処理を追記しました。
プレイヤーの変更
ここまでできたら、最後にプレイヤーキャラに少し手をくわえます。
アニメーターコントローラーの変更
まず、プレイヤーの「やられ時」のアニメーターの状態をまだ作っていなかったのでここで作ります。下の図のように「Dead」という名前のBool型のパラメーターを作り、Player_Deadステート(※アニメーションはダメージステートと同じでOKです)を作ったら「Any State」から遷移するようにしましょう。
PlayerControllerの変更
そうしたら、PlayerControllerスクリプトも少し変更しておきます。スクリプトを下記のように変更してください(※適宜省略してあります)。「追加その2」または「変更」と書かれた部分が該当箇所です。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(SpriteRenderer))]
[RequireComponent(typeof(Animator))]
public class PlayerController : BaseCharacterController
{
//省略
protected override void Damage()
{
//既にダメージ状態(=無敵時間中)なら終了
if (damage)
{
return;
}
//ヒットポイントを-1
//Hpプロパティにより、HPが0になると自動的にDead()が呼ばれる(※BaseCharacterController参照)
Hp--;
if(Hp > 0)
{
StartCoroutine("DamageTimer");
}
else
{
//追加その2
Dead();
}
}
//省略
protected override void Dead()
{
isActive = false;
animator.SetBool("Dead", true); //変更
//追加その2
rigidBody2D.velocity = Physics2D.gravity / rigidBody2D.gravityScale;
gameManager.GameOver();
}
//省略
}
変更点は、
- ダメージを受けた時にHPが0以下ならDeadメソッドを呼ぶようにした
- DeadメソッドではアニメーターがDeadステートになるようにして、GameManagerのゲームオーバー処理を呼ぶようにした
といった感じですね。これでクリア・ゲームオーバー処理を行うための変更作業が一通り完了しました。


