Mainシーンをステージクリア制にして、クリアするとリザルトシーンではなく、次のステージが開始するようにします。
ハイスコアの更新を目指してクリアしていくようにします。
Mainシーンを開きます。
ヒエラルキー内にてcreate -> Create Emptyを選択し、空のゲームオブジェクトを作成します。
名前を「StageManager」に変更します。
ヒエラルキーの「ScoreCanavas」内にて create -> UI -> Text を選択して新しいTextオブジェクトを作成します。
名前を「LevelText」に変更します。
「LevelText」をダブルクリックして配置された位置まで移動し、位置をゲームシーン上で調整します。
その後「LevelText」をDuplicate(複製)して名前を「LevelLabel」に変更します。
Text内に「Level : 」と書き込んで、位置をLevelTextの位置に合わせて調整をします。
いずれもAnchor機能を利用して画面サイズなどによってレイアウトが変更になったときにも、正常な位置に表示されるようにします。
Assets -> Scriptフォルダ内で右クリックをして create -> C# scrptを選択します。
名前を「LevelManager」に変更します。
下記のソースコードを書き込みます。
LevelManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class LevelManager : MonoBehaviour {
[SerializeField] Text levelText; // レベルの表示用。インスペクタで指定可能
[SerializeField] StartShot startShot; // ボールの制御用
public static int level; // ステージをクリアした回数。シーンをまたいでも引き継ぐようにpublic かつ staticにする
public static bool isStart; // ゲーム開始かどうかを判断するフラグ。falseなら開始前。trueならゲーム中と判断する
void Start ()
{
if(!isStart) // isStartのフラグを確認し、Falseであれば実行される。「!isStart」は「isStart == false」と同義。
{
level = 0; // レベルを0にする
isStart = true; // ゲーム開始のフラグを立てる。タイトル画面へ戻るとリセットされるようにResetFlags.csで管理する
}
levelText.text = level.ToString(); // levelをLevelTextに表示
}
public void LevelUp() // 外部(GameMaster.cs)より呼ばれるメソッド
{
startShot.BallDestroy(); // ボールを制御するメソッドの呼び出し
level ++ ; // levelを加算する
StartCoroutine("NextLevel"); // コルーチンの呼出し
}
IEnumerator NextLevel() // コルーチン
{
Debug.Log("Please press key");
while(!Input.GetKey("space")) yield return null; // スペースキーの入力待ち
SceneManager.LoadScene("Main"); // スペースキーが押されたらMainシーンを呼び出す
Debug.Log("Done!");
}
}
このスクリプトをMasterオブジェクトにアタッチします。
Masterゲームオブジェクトのインスペクターを確認してください。
LevelManager スクリプトに、public 修飾子で宣言した変数のアサイン情報が表示されますので、そちらを登録します。
アサインは、ヒエラルキーにあるゲームオブジェクトをドラッグアンドドロップすることで、
そのゲームオブジェクト、あるいはそのゲームオブジェクトが持っているコンポーネントやスクリプトを情報として変数に代入することを言います。
LevelText 変数には、先ほど作成した LevelText ゲームオブジェクトをドラッグアンドドロップしてアサインしてください。
自動的に、LevelText ゲームオブジェクトの持つ、Textコンポーネントの情報が、この変数に代入されます。
これで、LevelText 変数を通じて、ゲーム画面上に Level の値を表示する準備が整いました。
StartShot 変数には、StartShotスクリプトがアタッチされているゲームオブジェクトを、ここにアサインすることで情報を登録できます。
ヒエラルキーにある、Ball ゲームオブジェクトに StartShot スクリプトがアタッチされていますので
Ball ゲームオブジェクトをドラッグアンドドロップして、ここにアサインしてください。
これで StartShot 変数を通じて、Ball ゲームオブジェクトの StartShot スクリプトを操作できるようになりました。
Mainシーンにてゲームをクリアした場合、リザルトシーンには遷移せずにMainシーンを再度読み込み
Levelを1つ加算してステージが再度始まるようにします。
Resultシーンで作成したリザルト表示用のCanvasをMainシーンにも追加します。
ResultシーンのCanvasをコピー(あるいはプレファブ化)して、Mainシーンに追加します。
名前をResultCanvasに変更します。
ResultTextのTextからはGameOverの文字を削除して、空白の状態にしておいてください。
ここにはステージクリア時に文字が表示されるようにします。
GameMaster.csを変更します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI; // <= 追加する
public class GameMaster : MonoBehaviour {
public int boxNum;
public float nowTime;
[SerializeField] Text resultMessageText; // <- 追加する。クリアした際に「クリア」と表示するテキスト
private bool isClear; // <- 追加する。クリアした状態にするフラグ
// Use this for initialization
void Start () {
nowTime = 0;
}
// Update is called once per frame
void Update () {
nowTime += Time.deltaTime;
if(!isClear){ // <= ここから
{
if (boxNum <= 0)
{
StageClear(nowTime.ToString("F0") + "秒でクリアできた!"); //<=====秒数をstring型にキャストして引数へ <= ここの呼び出すメソッドを変更する
isClear = true;
}
} // <= ここまでを追加する
}
void StageClear(string resultMessage) // <= ここから
{
resultMessageText.text = resultMessage; // 画面にクリア状態を表示する(ResultTextのTextは空白にしておく)
FindObjectOfType<LevelManager>().LevelUp(); // LevelManagerのLevelUpメソッドを呼び出す
} // <= ここまでを追加する
public void GameOver(string resultMessage) { // 引数をもたせた
DataSender.resultMessage = resultMessage; // 受け取った引数をstatic変数へ格納
SceneManager.LoadScene("Result");
}
}
ゲームクリアの判定だけでは、ゲーム内のボールは動いたままです。
そのため、ゲームクリアと同時に、ボールを非アクティブ(あるいは破壊)するようにします。
StartShot.csを修正します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StartShot : MonoBehaviour {
// Use this for initialization
void Start () {
transform.eulerAngles = new Vector3(0, Random.Range(30, 120), 0);
gameObject.GetComponent<Rigidbody>().AddForce(transform.forward * 500);
}
// Update is called once per frame
void Update () {
}
public void BallDestroy() // <= ここから
{
this.gameObject.SetActive (false); // <= どちらかを書く。上はアタッチされているオブジェクトを非アクティブ。下はこのオブジェクトを破壊する。
Destroy(this.gameObject);
} // <= ここまでを追加する
}
LevelManager内には、public staticの変数が2つあります。
これらはシーンを遷移してもその中身が保持されますが、それはタイトル画面などに戻っても保持されたままです。
そこでタイトル画面より新しくゲームを開始すると、isStartのフラグが降りるように、Titleシーンに新しいスクリプトを追加します。
Scripts フォルダの中で右クリックをして Create -> C# Script を選択し、名前を「ResetFlags」と変更します。
ResetFlags.csを下記のように書き込みます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ResetFlags : MonoBehaviour {
// Use this for initialization
void Start ()
{
LevelManager.isStart = false; // isStartのフラグをfalseにする。public staticなのでどこからでも参照して変更できる。
}
}
このスクリプトが有効になるように、TitleシーンにあるMasterオブジェクトにアタッチします。