1つのスクリプトでゲームを動かす
CoddyのUnityジャーニー「本格的なゲームを作る」セクションの一部。レッスン 12/56。
スコアをプレイヤーのスクリプトに、ライフをヘルス用スクリプトに、ゲームオーバーの判定を3つ目のスクリプトに置くと、それぞれのスクリプトで他のスクリプトの数値が必要になり、新しいルールを追加するたびに複数のファイルを変更することになります。Unityのゲームでは通常、これらの数値を専用の空のGameObjectにアタッチした1つのスクリプト、GameManagerにまとめます。GameManagerがスコアとライフ、そしてゲームを終了するルールを管理します。他のスクリプトは、GameManagerのパブリックメソッドを呼び出して、起きたことを報告するだけです。このPK戦では、ゴールネットが各ゴールを報告します。
public class GameManager : MonoBehaviour
{
private int goals;
private int shotsLeft = 5;
public void ShotTaken(bool scored)
{
if (shotsLeft == 0) return;
shotsLeft--;
if (scored) goals++;
Debug.Log("Goals: " + goals + ", shots left: " + shotsLeft);
if (shotsLeft == 0) Debug.Log("Full time: " + goals + " goals");
}
}// Net.cs、ゴールのトリガーにて
public GameManager game;
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Ball")) game.ShotTaken(true);
}ゴールネットは、残りのシュート数やゲームが終了するタイミングを知りません。ゴールを報告し、その意味をマネージャーが判断します。キーパーのスクリプトは、セーブをgame.ShotTaken(false)で報告します。シュート数3回のPK戦にするには、1つのスクリプト内の数値を1か所変更するだけです。ShotTakenの先頭にある判定によって、試合終了後に転がり込んだボールが得点に加算されるのを防ぎます。
InspectorでGameManagerオブジェクトをgameフィールドにドラッグして割り当てると、Unityがそのオブジェクト上のGameManagerスクリプトを見つけます。マネージャーはHUDを管理する場所でもあります。スコアテキストとゲームオーバーパネルを保持させれば、数値を変更するのと同じメソッドで画面も更新され、他のスクリプトがUIに触れることはありません。
チャレンジ
簡単宝石探しです。矢印キーでPlayerを動かします(スクリプトは準備済みです)。宝石を取るとそのpoints分のポイントを獲得し、爆弾に当たるとライフを失います。GameManagerがこれらを管理します。Inspectorでは、各宝石と爆弾のgameフィールドはすでにGameManagerオブジェクトに、GameManagerのフィールドはHUDとPlayerに紐付けられています。
GameManager.csでは:
AddScore(int points)はポイントをscoreに加算し、Score: 6のようにscoreTextに表示します。LoseLife()はlivesを1減らし(開始時は3)、Lives: 2のようにlivesTextに表示します。livesが0になるとゲームオーバーです。gameOverPanelを表示し、Playerのスクリプトを無効にして矢印キーが効かないようにします。その後は、AddScoreを呼び出しても何も変わりません。
Gem.csとBomb.csでは:Player(タグPlayerが付いています)が宝石または爆弾に触れると、ゲームに通知し(宝石ならそのpoints、爆弾ならライフを1つ失います)、自身を削除します。
Playを押して、宝石を集めて爆弾に当たったら、Checkを押してください。
自分で試してみよう
using UnityEngine;
using TMPro;
public class GameManager : MonoBehaviour
{
public TMP_Text scoreText;
public TMP_Text livesText;
public GameObject gameOverPanel;
public Player player;
private int score;
private int lives = 3;
private bool gameOver;
public void AddScore(int points)
{
// ゲームオーバーでなければ、ポイントを加算して新しいスコアを表示する
}
public void LoseLife()
{
// ライフを1つ減らして表示する。ライフが0になったらゲームオーバー
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。