Unityに関連する記事です

 以下の内容で実装していきます。

35.セーブ・ロード機能を追加する



実装する概要


 ゲーム中の機能として、ゲームデータのセーブとロード機能を追加します。
いずれもボタンを用意し、タップすることで機能を実行します。

 セーブボタンを押すことで、現在再生中のシナリオデータの番号でセーブを行います。シナリオデータ中は1つの分岐につき1回だけセーブできるように制御します。
再生中のメッセージ単位ではなく、シナリオデータの番号単位でのセーブです。次のシナリオデータに移動すれば再度セーブが可能になります。

 ロードボタンを押すことでロード専用のポップアップが開き、セーブされているデータがボタンとして表示されます。
シナリオデータの分岐番号は表示されず、セーブデータの通し番号とセーブした時間が表示されます。


実装動画 

Title => DataLoad
https://gyazo.com/31713d0142b848a24dc98960b1d627ec


Title => SaveData なし
https://gyazo.com/05b590ff44da129ec754bcf85c6d3161


シナリオ1でセーブなし確認。その後セーブしてロード
https://gyazo.com/2af9ecbebe816c3ca299d643c50e8f4c


設計


 セーブ機能は、現在再生されているシナリオデータの番号を保存する機能です。シナリオデータの番号と保存を実行した時刻が PlayerPrefs クラスを利用してセーブされます。

 ロード機能はセーブしたデータが1つ以上ある場合に、そのデータ単位でのロードを行い、ロードしたシナリオデータの番号の最初のメッセージからゲームを再開できる機能です。

 次のような設計を行います。

<セーブ>
 ・セーブはGameシーンの間に、シナリオデータ1つ(分岐)につき1回実行できる
 ・ゲーム中でセーブボタンを押す
 ・セーブが実行されて、セーブボタンが一時的に押せなくなる
 ・次のシナリオデータの再生が始まると、再度セーブボタンが有効になる


<ロード>
 ・セーブはGameシーン、あるいはTitleシーンの間に実行できる
 ・ゲーム中でロードボタンを押す
 ・ロードが実行されて、ロード用ポップアップが画面前面に生成される
 ・ポップアップの中にはセーブデータ1つにつき1つの選択ボタンが生成される
 ・選択ボタンには通し番号とセーブしたデータの時間が表示される
 ・選択ボタンを1つ選択すると、そのデータがロードされて、自動的にポップアップが閉じ、そのシナリオデータの番号からゲームが再開される
 ・閉じるボタンを押した場合にはロード用ポップアップを閉じる


実装手順


 以下の手順で実装を行います。手順が多いため、2回に分けて実装手順を説明します。
ここでは【5】〜【9】までを対象とします。

 1.GameData スクリプトを修正し、セーブ・ロード機能にかかわる処理を追加する
 2.ロード用ポップアップである、DataLoadPopUp ゲームオブジェクトを作成する
 3.ロード用ボタンである、LoadDataSelectButton ゲームオブジェクトを作成する
 4.LoadDataSelectButton スクリプトを作成し、LoadDataSelectButton ゲームオブジェクトにアタッチして、プレファブにする

 5.DataLoadPopUp スクリプトを作成し、DataLoadPopUp ゲームオブジェクトにアタッチして、プレファブにする
 6.TextMessageViewew スクリプトを修正して、セーブ・ロード機能にかかわる処理を追加する
 7.GameDirector スクリプトを修正して、セーブ・ロード機能にかかわる処理を追加する
 8.Title スクリプトを修正して、セーブ・ロード機能にかかわる処理を追加する
 9.ゲームを実行して動作を確認する


新しく学習する内容


・Dictionaryの実装例 〜Addメソッド、KeyValuePair型構造体〜


5.DataLoadPopUp スクリプトを作成し、DataLoadPopUp ゲームオブジェクトにアタッチして、プレファブにする


 先ほどの手順で作成した DataLoadPopUp ゲームオブジェクトを制御するためのスクリプトを作成します。


DataLoadPopUp スクリプトを作成する



DataLoadPopUp.cs

 <= クリックすると開きます



<Dictionaryの実装例 〜Addメソッド、KeyValuePair型構造体〜>


 DicitonaryはListなどと同じコレクションと呼ばれる機能です。KeyとValueをセットにして要素を登録・まとめて(コレクション)いくことが出来ます。

SamuraiBlog様
【C#入門】DictionaryのKey、Valueの使い方(要素の追加、取得も解説)
https://www.sejuku.net/blog/41326
 

 Dicitonaryクラスには色々な機能がありますが、今回使用している機能について説明していきます。


宣言

 まずは宣言です。なおDicitonary機能を使うためには using System.Collections.Generic の宣言が必要になりますが
この宣言はスクリプトファイルを作成すると自動的に追加されていますので、削除していない限りは宣言すれば使用できると思っていて問題ありません。

 Dictionary<Keyの型名, Valueの型名> 変数名 = new Dictionary<Keyの型名, Valueの型名>(コンストラクタ(普段は空でよい));

 引数を指定してコンストラクタ・メソッドを利用したり、宣言と同時に初期化をすることも出来ます。
今回はその両方を利用しています。(変数のスコープがメソッド内のみで使用できればよいため、宣言フィールドではなくメソッド内で宣言しています。)

コンストラクタ・メソッドでは、GameData.instance.GetSaveDatas()メソッドを実行し、戻り値としてDictionaryを受け取り、それを初期化値としています。


<コンストラクタ・メソッドなし>
 // Dictionaryを初期化(引数がないので、コンストラクタ・メソッドは利用していないため、値は代入されていない)
  Dictionary<int, string> saveDatas = new Dictionary<int, string>();


<コンストラクタ・メソッドを利用>
 // コンストラクタ・メソッドを使ってDictinaryを初期化
  Dictionary<int, string> loadDatas = new Dictionary<int, string>(GameData.instance.GetSaveDatas());

 Keyがint型、Valueがstring型、変数名は loadDatas にしています。


Addメソッド

 Addメソッドでは引数に指定した値を要素に追加することが出来ます。ListのAddメソッドと同じですが、KeyとValueの両方を指定して値を追加します。
処理が長くて読みにくいかもしれませんが、引数の中のカンマまでが1つの値です。

 // セーブデータのDictionaryに追加
 saveDatas.Add(PlayerPrefs.GetInt(CURRENT_BRANCH_NO + i.ToString()), PlayerPrefs.GetString(SAVE_TIME_NO + i.ToString()));


KeyValuePair型構造体

 KeyValuePair構造体は、Dicitonary内のKeyとValueの両方を取得する処理です。

 次の処理では、この処理を利用しています。
Dictionary型の loadDatas 変数の要素を foreach を利用して1つずつ取り出し、item 変数へ代入しています。
そして item 変数の持つ Key と Value の情報を利用しています。

 foreach (KeyValuePair<int, string> item in loadDatas) {

    // ロードボタンの初期設定
      loadSelectButton.SetUpLoadSelectButton(item.Key, item.Value, this, i);
  }


DataLoadPopUp スクリプトを作成し、DataLoadPopUp ゲームオブジェクトにアタッチして設定する


作成した DataLoadPopUp スクリプトを、DataLoadPopUp ゲームオブジェクトにアタッチします。

 DataLoadPopUp ゲームオブジェクトを選択し、インスペクターを確認してください。
DataLoadPopUp スクリプトのアサイン情報が表示されますので、そちらの設定を行います。


 loadSelectbuttonPrefab 変数には、ロード用のボタンのプレファブ(ゲームオブジェクト)をアサインします。
Prefabフォルダにある、LoadDataSelectButton ゲームオブジェクトをドラッグアンドドロップしてアサインしてください。
この情報を利用して、ポップアップ内にロード用のボタンを生成します。


 loadSelectButtonList 変数には、ポップアップ生成時に生成されるロード用ボタンが代入されます。
現在は Size 0 になっていますので、こちらはそのままにしておいてください。


 loadSelectButtonTran 変数には、生成するロード用ボタンの位置を指定するための情報です。
ヒエラルキーの DataLoadPopUp ゲームオブジェクト内にある、LoadSelectButtonTra_Content ゲームオブジェクトをドラッグアンドドロップしてアサインしてください。
ロード用のボタンはこの位置に生成されることになり、このゲームオブジェクトの持つGridLayoutGroupコンポーネントの機能によって、縦方向に一定の距離を置いて自動的に整列されます。


 canvasGroup 変数は、CanvasGroupコンポーネントの制御用の情報です。ヒエラルキーの DataLoadPopUp ゲームオブジェクトをドラッグアンドドロップしてアサインしてください。
そうすることにより、DataLoadPopUp ゲームオブジェクトにアタッチされている CanvasGroup コンポーネントの情報がアサインされます。


 btnClose 変数には、ポップアップを閉じるボタンの情報をアサインします。
ヒエラルキーの DataLoadPopUp ゲームオブジェクト内にある、btnClose ゲームオブジェクトをドラッグアンドドロップしてアサインしてください。
こうすることで、btnClose ゲームオブジェクトにアタッチされている Button コンポーネントの情報がアサインされて、制御出来るようになります。


DataLoadPopUp ゲームオブジェクト インスペクター画像



DataLoadPopUp ゲームオブジェクト インスペクター画像



DataLoadPopUp ゲームオブジェクトをプレファブにする


 スクリプトの設定も終了しましたので、DataLoadPopUp ゲームオブジェクトをプレファブにします。
プレファブ後はヒエラルキーより削除しておいてください。


6.TextMessageViewewスクリプトを修正して、セーブ・ロード機能にかかわる処理を追加する

設計


 セーブ・ロード機能を実装するための処理を追加していきます。

 今回はGameシーンの MessageWindow ゲームオブジェクト内にセーブボタンとロードボタンを設置していますので
これらのボタンを制御する変数を用意し、各ボタンを押下した際の処理をおこなえるようにします。

 それらのボタンに対応する OnClickSaveメソッドとOnClickDataLoadメソッドの2つを新しく追加し、ボタンからこのメソッドを呼び出すようにして実行します。

 ロードボタンを押した際にはポップアップを生成する必要がありますので、先ほどプレファブにした DataLoadPopUp ゲームオブジェクトのアサイン情報を登録し、
それに関連する変数を合計で3つ追加します。


TextMessageViewewスクリプトを修正する



TextMessageViewer.cs

 <= クリックすると開きます。



TextMessageViewerゲームオブジェクトを設定する


 スクリプトの修正が終了したので、TextMessageViewerゲームオブジェクトを選択してインスペクターを確認します。
新しく追加した変数が4つ表示されていますので、これらを順番にアサインしてください。


  btnSave 変数と btnLoad 変数にはそれぞれの処理に対応するボタンをアサインします。今回はGameシーンのMessageWindow内にこれらのボタンを設置していますので
そのゲームオブジェクトをそれぞれの変数にドラッグアンドドロップしてアサインします。


 dataLoadPopUpPrefab 変数は、先ほどプレファブにした、DataLoadPopUp ゲームオブジェクトをドラッグアンドドロップしてアサインします。
必ず Prefabs フォルダにある DataLoadPopUp ゲームオブジェクトを使ってください。


 canvasTran 変数には、DataLoadPopUp ゲームオブジェクトを生成する位置情報をアサインします。 Canvas 内に生成したいので、
ヒエラルキーにある Canvas ゲームオブジェクトをドラッグアンドドロップしてアサインします。


TextMessageViewerゲームオブジェクト インスペクター画像



7.GameDirector スクリプトを修正して、セーブ・ロード機能にかかわる処理を追加する

設計


 Startメソッド内を修正して、ロードされたデータがあった場合にはそのシナリオデータの番号をセットし、
そうでない場合には最初からシナリオが始まるように初期値をセットする処理を追加します。

 手順11以降、割愛が続いているため、ここでは全文掲載します。
ここまでの手順がすべて記載されていますので、抜けている処理がないか、確認しながら進めてください。


GameDirector スクリプトを修正する



GameDirector.cs

 <= クリックすると開きます。



 

8.Title スクリプトを修正して、セーブ・ロード機能にかかわる処理を追加する

事前準備


 Titleシーンの Canvas ゲームオブジェクト内に、ロード用のボタンを設置してください。位置や大きさは適宜に調整してください。


Titleシーン ヒエラルキー画像



Titleシーン SceneビューとGameビュー画像



 Titleスクリプトでは、この Titleシーンに設置したロード用のボタンを制御し、ボタンを押すことによってロード用のポップアップを生成するように処理を追加します。
新しく OnClickDataLoad メソッドを追加し、この中でポップアップの生成を実行します。

 変数にはボタン用の変数、ポップアップのプレファブを登録するための変数、生成位置を指定するための変数の3つの情報を新しく追加します。



Title スクリプトを修正する



Title.cs



Titleゲームオブジェクトの設定を行う


 スクリプトの修正が終了したので、Titleシーンへ移動し、Titleゲームオブジェクトを選択してインスペクターを確認します。
新しく追加した変数が3つ表示されていますので、これらを順番にアサインしてください。


 btnDataLoad 変数には、Titleシーンに設置している、ロード用のポップアップを生成するボタンをアサインします。
ヒエラルキーにある、ロード用のボタンのゲームオブジェクトをドラッグアンドドロップしてアサインしてください。
このボタンを押すと、ロード用のポップアップが生成されます。


 dataLoadPopUpPrefab 変数は、先ほどプレファブにした、DataLoadPopUp ゲームオブジェクトをドラッグアンドドロップしてアサインします。
必ず Prefabs フォルダにある DataLoadPopUp ゲームオブジェクトを使ってください。


 canvasTran 変数には、DataLoadPopUp ゲームオブジェクトを生成する位置情報をアサインします。 Canvas 内に生成したいので、
ヒエラルキーにある Canvas ゲームオブジェクトをドラッグアンドドロップしてアサインします。


Titleゲームオブジェクト インスペクター画像



9.ゲームを実行して動作を確認する


 ゲームを実行して動作を確認してみましょう。

 まずは Title シーンにおいてロードボタンを押下し、ロード用のポップアップが正常に生成されるか確認を行います。
セーブされたデータがありませんので、ポップアップ内にはロード用のボタンは生成されていないはずです。

 そのままゲームをスタートし、Gameシーンへ遷移してください。ロードしているデータがありませんので、以前と同じように
最初のシナリオからゲームがスタートするはずです。まずはこの2点が正常に動作するか、確認をしてください。


<検証動画> Title => SaveData なし
https://gyazo.com/05b590ff44da129ec754bcf85c6d3161


 問題なければ、任意の位置でセーブボタンを押し、セーブを実行してください。Debugを入れてあるので、セーブが実行された場合にはコンソールに表示が出ます。
セーブボタンは1つのシナリオデータの番号につき1回です。セーブボタンが押せなくなっているかも一緒に確認を行います。

 1つ先のシナリオデータまでゲームを進めていただき、そのシナリオデータでロードボタンを押します。
Titleシーンと同じようにロード用のポップアップが生成されて、今回はセーブデータがありますので、1つのロード用ボタンが一緒にポップアップ内に生成されているはずです。

 ボタンには通し番号とセーブした時間が表示されているかも確認しましょう。

 ロード用ボタンをおして、1つ前のシナリオからゲームが再開されるか確認します。問題なければゲームを停止します。


<検証動画> シナリオ1でセーブなし確認。その後セーブしてロード
https://gyazo.com/2af9ecbebe816c3ca299d643c50e8f4c


 最後に、Titleシーンからもう一度ゲームを開始し、ロードボタンを押してください。先ほどと同じようにロード用のボタンが1つ生成されていますので
そちらを押してください。ゲームがセーブしたシナリオデータの番号から再開されれば成功です。


<検証動画> Title => DataLoad
https://gyazo.com/31713d0142b848a24dc98960b1d627ec


<検証動画> サムネイル画像つき
https://gyazo.com/e48d65337f318430c04ad541dd46c1d8


<検証動画> サムネイル画像つき(デバッグログ表示あり)
https://gyazo.com/d797d8b9e26690f2cb2fef8c3cc586d9


 以上でこの手順は終了です。お疲れ様でした!

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu



技術/知識(実装例)

2Dおはじきゲーム(発展編)

2D強制横スクロールアクション(発展編)

3Dダイビングアクション(発展編)

2Dタップシューティング(拡張編)

レースゲーム(抜粋)

2D放置ゲーム(発展編)

3Dレールガンシューティング(応用編)

3D脱出ゲーム(抜粋)

2Dリアルタイムストラテジー

2Dトップビューアドベンチャー(宴アセット使用)

3Dタップアクション(NavMeshAgent 使用)

2Dトップビューアクション(カエルの為に〜、ボコスカウォーズ風)

VideoPlayer イベント連動の実装例

VideoPlayer リスト内からムービー再生の実装例(発展)

AR 画像付きオブジェクト生成の実装例

AR リスト内から生成の実装例(発展)

private



このサイト内の作品はユニティちゃんライセンス条項の元に提供されています。

管理人/副管理人のみ編集できます