見出し画像

【Unity】3Dローグライクゲームの作り方〜Step11-19〜

前回の記事はこちら
前回は宝箱を実装しました。

ターン数のセーブ

ターン数のセーブをするのをすっかり忘れていたので、今ここで実装します。
MapSaveDataクラスにパラメーターを追記します。

public int elapsedTurn;

次にSaveDataManagerクラスに以下を追記します。

private MapSaveData MakeMapData()
{
   MapSaveData mapSaveData = new MapSaveData();
   Rect2D[] dummyranges = new Rect2D[0];
   mapSaveData.floorNum = Field.floorNum;
   // 以下1行を追記
   mapSaveData.elapsedTurn = SequenceManager.elapsedTurn;
   MakeMapObjectData(stairs.transform, ref mapSaveData.stairs, ref dummyranges);
   MakeMapObjectData(rooms.transform, ref mapSaveData.roompositions, ref mapSaveData.roomranges);
   MakeMapObjectData(connections.transform, ref mapSaveData.connections, ref dummyranges);
   mapSaveData.map = field.GetMapData();
   return mapSaveData;
}

private void LoadMapData(SaveData saveData)
{
   Field.floorNum = saveData.mapData.floorNum;
   field.Reset();
   field.Create(saveData.mapData.map);
   // 以下1行を追記
   SequenceManager.elapsedTurn = saveData.mapData.elapsedTurn;
   for (int i = 0; i < 2; i++)
   {
       /*   省略   */
   }
   for (int i = 0; i < saveData.mapData.roompositions.Length; i++)
   {
       /*   省略   */
   }
   for (int i = 0; i < saveData.mapData.connections.Length; i++)
   {
       /*   省略   */
   }
}

// 宝箱関連でエラーが発生するのでついでに修正
private void LoadEnemyDatas(SaveData saveData)
{
   foreach (var data in saveData.enemyDatas)
   {
       ExcelActorData database = Resources.Load<ExcelActorData>("Datas/ExcelActorData");
       ExcelActorData.ActorData actorData =
           database.Data.Find(n => n.id == data.parameter.id);
       GameObject enemyObj = (GameObject)Resources.Load("Prefabs/"+actorData.prefab);
       GameObject enemy = Instantiate(enemyObj, enemies.transform);
       LoadActorData(data, enemy.transform);
       // 以下3行を変更
       EnemyOperation enemyOperation = enemy.GetComponent<EnemyOperation>();
       if (enemyOperation != null)
           enemyOperation.target = player.GetComponent<ActorMovement>();
   }
}

実行してみます。

スクリーンショット 2020-10-30 0.20.57

無事取得できています。
ちゃんとロードもできるか確認しておいて下さい。

スタート画面(仮)の作成

今回は仮のスタート画面を作成しようと思います。
とりあえずタイトルと「Start」、「Continue」、「Exit」ボタンがあるといいですね。イメージはこんな感じです。

画像2

ユニティちゃんロゴのところにユニティちゃんを表示する予定です。

スタートシーンの作成

スタート画面を作成するにあたり、シーンを新たに作成します。その前に、今のシーンを保存しておいて下さい。
それではUnityエディター上部の「ファイル」→「新しいシーン」を選択します。すると新しいシーンが作成されるはずです。これで保存しようとすると下記の画像が表示されるはずです。

スクリーンショット 2020-10-30 12.34.24

これのSave Asには「StartScene」と入力し、WhereにはAssets/Scenesフォルダを指定しておきましょう。
保存できたら、画面を作っていきます。筆者は以下のようになりました。

スクリーンショット 2020-10-30 14.49.54

最初にイメージしていたものとは少し異なる感じになりました。
ちなみにヒエラルキータブ内はこんな感じになっています。

スクリーンショット 2020-10-30 14.50.28

全て今までの応用でできるので説明は省略させて頂きます。
ただし、StartButtonは「作成」→「UI」→「ボタン」で作成できるButtonを使用して下さい。
次にEventSystemのイベントシステムコンポーネントの「最初に選択された」項目にStartボタンのオブジェクトを指定しておきましょう。ゲームスタート時にStartボタンが選択された状態になります。
同時にStartボタンのボタンコンポーネントのナビゲーションを「明示的」にし、Select On UpにExitボタンのオブジェクトを、DownにContinueボタンのオブジェクトを指定します。こうすることでStartボタンからExitボタンへ選択を移動することができるようになります。
同様に他のボタンオブジェクトにも設定しておきます。

StartButtonスクリプト

スクリプトを書いていきます。新しいスクリプトを作成し、名前を「StartButton」にしましょう。そこに以下のように記述します。

using UnityEngine;
using UnityEngine.SceneManagement;

public class StartButton : MonoBehaviour
{
   /*
   * ゲームを開始
   */
   public void GameStart()
	{
       SceneManager.LoadScene("MainScene");
	}

   /*
   * ゲームを再開
   */
   public void GameContinue()
	{

	}

   /*
   * ゲームを終了
   */
   public void GameEnd()
	{
       #if UNITY_EDITOR
             UnityEditor.EditorApplication.isPlaying = false;
       #elif UNITY_STANDALONE
             UnityEngine.Application.Quit();
       #endif
   }
}

Continue機能はプレイヤー向けのセーブ機能を実装した時に改めて実装したいと思います。
それでは作成したボタンにそれぞれスクリプトをアタッチしましょう。
プレハブ化している方はプレハブ自体にアタッチすると楽です。
次にボタンコンポーネントの「クリック時()」という項目を以下のように設定して下さい。

スクリーンショット 2020-10-30 16.30.26

これでこのボタン押下時はこのメソッドを呼び出すことができるようになりました。
その他のボタンにも同じように設定して下さい。
それではテストプレイ......といきたいところですが、ちょっと待って下さい。その前にビルド設定でシーンを登録する必要があります。
上部の「ファイル」→「ビルド設定」でこんな画面が出ると思います。

スクリーンショット 2020-10-30 16.38.32

ビルドに含まれるシーンに「StartScene」と「MainScene」をドラッグ&ドロップします。すると上記のようになります。こうしないとシーン遷移に失敗しますので注意して下さい。
それでは実行してみます。

シーン遷移

無事ゲーム画面に進みました!

(オプション)ボタン押下時にフェードアウトする

折角なのでボタンを押した時にフェードアウトするようにしてみましょう。
パネルを追加し、以下のように設定して下さい。​

スクリーンショット 2020-10-30 16.53.08

次にStartButtonスクリプトを以下のように変更します。変更点が多いので全て載せました。

using UnityEngine;
using UnityEngine.SceneManagement;

public class StartButton : MonoBehaviour
{
   public FadeInOut fade;

   private int type = 0;

   private void Update()
   {
       if (type > 0)
       {
           if (fade.Fade(true))
           {
               switch (type)
               {
                   case 1:
                       SceneManager.LoadScene("MainScene");
                       break;
                   case 2:
                       break;
                   case 3:
                       Exit();
                       break;
               }
           }
       }
   }

   /*
   * ゲーム開始
   */
   public void GameStart()
	{
       if (type == 0) type = 1;
	}

   /*
   * ゲームを再開
   */
   public void GameContinue()
	{
       if (type == 0) type = 2;
   }

   /*
   * ゲームを終了
   */
   public void GameEnd()
	{
       if (type == 0) type = 3;
   }

   private void Exit()
   {
       #if UNITY_EDITOR
               UnityEditor.EditorApplication.isPlaying = false;
       #elif UNITY_STANDALONE
               UnityEngine.Application.Quit();
       #endif
   }
}

ビルドしたらコンポーネントのFadeにパネルのFadeを設定しておきます。
実行すると、フェードアウトしてからゲーム開始したり終了したりするはずです。

(オプション)クリックではボタンを押せないようにする

上にパネルを被せることで可能です。Fadeパネルを作った方はそれを使用しても大丈夫です。
被せたパネルのレイキャストターゲットのチェックを入れましょう。するとマウスではボタンを選択できなくなったはずです。

おまけ:SaveDataEditorでセーブデータを上書き保存すると、再度取得した時に表示がおかしくなる

すみません! 代入を忘れていました。

void WriteSaveData(string k , string data)
{
   data = data.Replace("\r", "");
   data = data.Replace("\n", "");
   PlayerPrefs.SetString(k, data);
}

これで大丈夫なはずです。
ちなみにMacだとカーソルが一定以上進まなかったりしますが、表示されなくても選択はできるようなので書き換えは普通にできます。

ということで今回はここまでに致します。
次回はゲーム中にメニュー画面を表示するところから始めたいと思います。

この記事が気に入ったらサポートをしてみませんか?