Unityに関連する記事です

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

31.すべてのエンディングをコンプリートすると新しい機能が開放される処理を実装する



 新しく学習する内容です。

 ・PlayerPrefsを利用したデータのセーブ・ロード
 ・PlayerPrefsの初期化



31.すべてのエンディングをコンプリートすると新しい機能が開放される処理を実装する


 複数のエンディングがあるゲームにおいて、すべてのエンディングをコンプリートすると新しい機能が開放される処理を追加します。


事前準備


 事前準備としまして、Gameシーン以外のTitleシーンを作成し、Canvas内にボタンを1つ用意しておいてください。
このボタンはActiveスイッチをオフにして、見えない状態(非アクティブ)にしておきます(ヒエラルキー上では灰字で表示)

 またGameDataゲームオブジェクトも必要になります。このゲームオブジェクトはシングルトンですので、複数のシーンに設置してあっても常に1つに制御されます。
GameシーンにあるGameDataゲームオブジェクトをプレファブして、Titleシーンに設置してください。


動画 Activeスイッチをオフにしておく
https://gyazo.com/5c01d86a174b3a6af59f894b759706d4

TitleシーンのヒエラルキーとSceneビューのサンプル画像


 
 今回の機能では、エンディングをコンプリートした状態でゲームを起動すると、非アクティブになっているボタンが自動的にアクティブになる処理になります。
他にも応用できますので、実装方法を考えてみてください。


設計


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

 ・エンディングを見る => まだ見たことのないエンディングの場合には、エンディングの番号を保存する
 ・ゲーム開始時にエンディングの番号を順番に確認して、コンプリート確認を行う => エンディングをコンプリートしている場合には新しい機能が開放される

 今回の場合は、全エンディングをコンプリートしている場合にはタイトル画面に新しいボタンが追加されるようにします。
そのため、エンディングのコンプリート確認はタイトル画面で行うようにします。

 また1回見たエンディングについてはエンディングの保存対象から外すように制御をします。


実装手順


 以下の手順で実装を行います。

 1.Excelファイルを修正して、エンディング番号を追加する
 2.SenarioMasterDataスクリプトを修正して、エンディングの情報(エンディング番号)を登録できるようにする
 3.GameDataスクリプトを修正して、プレイヤーが見たエンディングの番号をセーブしたり、ロードする機能を追加する
 4.TextMessageViewewスクリプトを修正して、エンディング番号にかかわる処理を追加する
 5.Titleシーン用のTitleスクリプトを作成し、Titleゲームオブジェクトにアタッチする
 6.ゲームを実行して動作を確認する


1.Excelファイルを修正して、エンディング番号を追加する


 Excelファイルの最後に新しい項目として endingNo を追加します。
0の場合はエンディング対象なし、1以上の数字がエンディングの対象となり、その値がそのままエンディングの番号となります。


サンプル Jsonファイル

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



2.SenarioMasterDataスクリプトを修正して、エンディングの情報(エンディング番号)を登録できるようにする


 【1】で作成したExcelデータをゲーム内に読み込めるように、SenarioMasterDataスクリプト(あるいはSenarioスクリプト)を修正し、 endingNo を追加します。


Excel => Jsonからスクリプタブル・オブジェクトを作成している場合


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



Excel ImporterでExcelファイルから直接スクリプタブル・オブジェクトを作成している場合


Scenario.cs

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



3.GameDataスクリプトを修正して、プレイヤーが見たエンディングの番号をセーブしたり、ロードする機能を追加する


 GameDataスクリプトを修正して、エンディングの総数を登録出来るようにするために、新しく変数を3つ追加します。
合わせて、プレイヤーが見たエンディングの番号をセーブしたり、ロードする処理も追加します。

 エンディングを見た際に、そのエンディングが初めて見たエンディングである場合に限り、SaveEndingDataメソッドでエンディング番号をセーブします。
この制御を追加しておかないと、見たことのあるエンディングを再度見た場合にもセーブされていまい、不具合が発生します。

 見ているエンディングの保存データをロードする際には、LoadCheckEndingDataメソッドを呼び出し、コンプリートしているかどうかの判定も一緒に行うようにします。 


GameData.cs

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



<PlayerPrefsを利用したデータのセーブ・ロード>


 UnityにはPlayerPrefs(プレイヤー・プリフ、プレイヤー・プリファレンス)という、ゲームデータをセーブ・ロードする機能を持つクラスがあります。

 PlayerPrefsクラスにはゲームデータに関わる複数のメソッドが用意されていますが、今回はint型でセーブを行うSetIntメソッドを利用しています。
合計で4つのメソッドを使っていますので、順番に説明します。



PlayerPrefs.SetInt(string key, int value)


 第1引数で用意した key の名前で value の情報を保存するために設定します。Set〜メソッドは3種類あり、今回はint型で値を設定するSetIntメソッドを使用しています。
Set〜メソッドは扱う型は異なりますが、構造はすべて同じです。

 private string ENDING = "ending_";

 PlayerPrefs.SetInt(ENDING + endingNo.ToString(), endingNo);

 例えば endingNo = 1 である場合には、

 PlayerPrefs.SetInt("ending_1", 1);

 という処理が行われていることになります。ending_1 という名前で 1 の値をセーブする、という内容です。
処理は変数同士の扱いであるため、内容が分かりにくいですが、このように常に変数の中身がどのようになっているかを考えて処理を読むようにしてください。


PlayerPrefs.Save()


 Saveメソッドを実行することで、Set〜メソッドで設定した値を key として保存します。

 Saveメソッドが実行されると、UnityエディターではPC内にセーブされ、Androidなどの端末の場合には、ゲーム内の専用の保存場所にセーブされます。
この処理を実行することでゲームを終了しても、セーブした値を読み込むことが出来るようになります。

 Set〜メソッドだけではセーブされませんので、Set〜メソッドとSaveメソッドは必ず1セットで使うことを覚えておいてください。

 一度セーブした情報を同じ key で保存した場合には上書きされます。またセーブした情報は自動的には破棄されません。


PlayerPrefs.HasKey (string key)


 HasKeyメソッドを実行すると引数で指定した key が現在セーブされている情報の中に存在しているかどうかを bool型で返してくれます。
セーブデータに key が存在している場合には true、存在していない場合(セーブされていない場合)には false が返ります。

 今回はENDING + i.ToString()を引数に指定していますので、"ending_i" の名前でセーブされているエンディングの番号があるかどうかを確認しています。
そしてセーブされている key があった場合のみ、データのロードを行うようにしています。

 if (PlayerPrefs.HasKey(ENDING + i.ToString())) {          
 

PlayerPrefs.GetInt (string key) 戻り値 int


 データのロードを行うメソッドです。Set〜メソッドと対応しているため、Get〜メソッドも3種類あります。

 GetIntメソッドでは、key で指定したデータをロードし、戻り値として int の値を返してくれます。
今回は戻り値を endingNos 変数(List<>型)に代入しています。

  // 見ているエンディングだけ読み込み、リストに追加
  endingNos.Add(PlayerPrefs.GetInt(ENDING + i.ToString()));

 なおGet〜メソッドは引数にオーバーロードがあります。
第2引数を指定すると、その値を初期値として代入するようになり、その後にロードを行ってデータがある場合には初期値を上書きします。

 セーブデータが存在しない場合には必要な処理になりますが、今回はデータがあることを確認してからロードを行っており、不要な処理であるため省略しています。
 

参考サイト
Unity公式スクリプトリファレンス
PlayerPrefs
https://docs.unity3d.com/ja/current/ScriptReferenc...



 スクリプトの修正が終了したら、GameDataゲームオブジェクトのインスペクターを確認します。
新しく追加した変数のうち、EndingConut 変数には、ゲームにおいて用意しているエンディングの総数を登録します。
まだエンディングの用意がない間は 0 にしておきます。

 LoadCheckEndingDataメソッドでは、このエンディングの総数と、プレイヤーが見ているエンディングの数とを照合して、コンプリート判定を行っています。


4.TextMessageViewerスクリプトを修正し、エンディング番号にかかわる処理を追加する


 複数の箇所で追記を行います。記載のないメソッドは変更なしのため、そのままで問題ありません。


 最初に宣言フィールドに変数を1つ追加し、シナリオデータの持つエンディングの番号を管理出来るようにします。

 SetUpScenarioDataメソッドを修正して、エンディングの番号を登録します。
エンディングの番号は 1 以上で設定されますので、0 の場合にはエンディングを持たないシナリオデータとなります。

 NextTouchメソッドを修正し、エンディングの番号を持つシナリオデータの場合には、エンディングの番号をセーブします。
このとき、すでに見ているエンディングの場合には番号の登録を行わないように制御をします。

 JudgeEndingメソッドを修正して、エンディングの番号が 0 ではない場合にはエンディングになるように制御を追加します。
 

TextMessageViewer.cs

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



5.Titleシーン用のTitleスクリプトを作成し、Titleゲームオブジェクトにアタッチする


 Titleシーンにスクリプトを追加します。
 すでにTitleシーン用のスクリプトを用意している場合には、そのスクリプトに、こちらのスクリプトの内容を追記してください。


Title.cs




 Titleスクリプトをアタッチするゲームオブジェクトを作成します。ヒエラルキー上で右クリックしてメニューを表示し、CreateEmptyを選択します。
名前を Title に変更します。Titleゲームオブジェクトは、Canvasの中に作成する必要はありません。

 Titleゲームオブジェクトに、Titleスクリプトをアタッチし、インスペクターを確認します。
btnNewGame変数のアサイン情報が表示されますので、Canvas内に作成してある btnNewGame ゲームオブジェクトをドラッグアンドドロップしてアサインしてください。


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



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


 GameDataゲームオブジェクトを選択してインスペクターにある EndingConut の値を 1 以上にします。
これでTitleスクリプトでのエンディング数のチェックが行われるようになります。


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



 ゲームを進めて、シナリオデータで用意したエンディングの番号が 0 以外の分岐を選択し、エンディングの番号が登録されるか、Debug.Logをみて確認を行います。
正常にセーブされたら、ゲームを停止して、再度ゲームを起動します。

 このときに見ているエンディングの数が 1 であれば、EndingConutの値と同じになるので、Titleスクリプトの isNewGame 変数が true になります。
合わせて、Titleシーン内で非アクティブであったボタンが表示されるようになります。


実装動画 .┘鵐妊ングのデータの読み込みが終わって、NewGameの条件を満たした場合にはチェックが入る(trueになる)
https://gyazo.com/625de186558f6d567bc31a6a1bbf6ba0


実装動画◆NewGameの場合には、新しくボタンが表示される
https://gyazo.com/a8d13582e6a09e5c311e08296457bcba


<PlayerPrefsの初期化>

 
 一度UnityからPlayerPrefsを使って保存されたデータは自動的には破棄されません。

 Unityの左上のメニューから Edit => Clear All PlayerPrefs を選択してください。これで何も保存されていない状態に戻ります。
デバッグを行う場合に活用してください。




 以上でこの手順は終了です。

コメントをかく


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

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

Menu



技術/知識(実装例)

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

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

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

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

レースゲーム(抜粋)

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

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

3D脱出ゲーム(抜粋)

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

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

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

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

VideoPlayer イベント連動の実装例

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

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

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

private



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

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