見出し画像

UnityのPlayerPrefsでオートセーブ/ロードを実装する(アセット不要)

こんにちは。「仕様です。」(@shiyoumasayume)という名前でSNSをやっているゲームプランナーです。

ふだんはコンシューマータイトルプロジェクトでディレクターやプロデューサーが旗を振ったイメージを具体的にゲームデザインするという仕事をやっています。

また最近では在宅での仕事も増え、結果として自分の自由な時間が増えました。

そこで勉強も兼ねて普段の業務では作れないようなゲームを個人開発したりしています。

今回はUnityで個人開発中のゲームをもとに外部アセットを使わずオートセーブ、オートロード機能を実装する方法についてまとめていこうと思います。

このnote単体で読んでいただいても大丈夫ですが、作っているゲームについての詳細を知りたいという方は開発内容まとめなどを見ていただけると嬉しいです!

 作成中のゲーム「Dr.Holeking」についての全記事はこちら

開発に使うもの

PC
・MacBook Air 2020 13インチモデル
・第10世代の1.2GHzクアッドコアIntel Core i7プロセッサ
・Intel Iris Plus Graphics
・16GB 3,733MHz LPDDR4Xメモリ
・1TB SSDストレージ
ゲームエンジン
・Unity バージョン2020.1.2f1
Google chrome
・調べ物をするときに
Twitter / note
・経過報告用

Macbook AirにUnityというツールを入れてゲームを作っていきます。

1台のノートPCだけでの開発というたいへんコンパクトな装備。M1チップの新型Macbook Airが発売され、「早い…早くない?」と首をかしげるばかりです。

ちなみに、ゲーム中のフォントやSE、BGM素材以外はすべてUnityをインストールするだけで作れる内容で構成しています。

作ろうとしているゲームの概要

今回作っている「Dr.Holeking」というゲームはこんな要素を持っています。

・ポストアポカリプス(崩壊後の世界)なSFモノ
・基地のリソースを管理して襲来する敵を倒す
・敵を倒して得たリソースを使って基地の地下を掘削し、地球の核へと到達する
・iPhoneの縦持ちでプレイ
・ゲーム名:Dr.Holeking

プレイヤーが遊ぶときの流れはこんな具合です。

1.基地のリソースを消費して基地設備を整える
2.襲来する敵を倒す
3.敵を倒して得たリソースでさらに基地を増築or地面の掘削を進める。

敗北条件:所有する基地の設備が襲来する敵を倒しきれなかった
クリア条件:特定の深度まで掘削を進めた

ここで遊べます!

作成中のゲームのプロトタイプをUnityRoomというフリーゲーム投稿サイトに登録しています。

遊んでいただけるととっても嬉しいです!

そもそも手動のセーブ、ロードを実装する方法

PlayerPrefsというUnityが提供しているスクリプトを使用します。

Int、Float、Stringの型に対応しており、整数や小数、文字列を保存しておく事が可能な機能です。

たとえば、ゲーム内通貨として「エネルギー」という数値があり、それをゲームを閉じて再開した後も保持できるようにしたい場合。

// EnergyNum変数をSaveEnergyNumという名前に格納する        
PlayerPrefs.SetInt("SaveEnergyNum",EnergyNum);

// Setした内容の保存を確定する
PlayerPrefs.Save();
■PlayerPrefs.SetInt()を使い、エネルギーの値を入れているInt型変数をSaveEnergyNumという名前に格納。

■PlayerPrefs.Save()でSetで格納された内容の保存を確定します。

ここでセーブした内容をロードしたいときは、

EnergyNum = PlayerPrefs.GetInt("SaveEnergyNum",0);

PlayerPrefs.GetInt("ロードしたいセーブ名")で取得し、変数に入れればOKです。

Int型の他、FloatやStringでも同様です。

オートセーブ、オートロードを設計する

オートセーブ、オートロードは上記の処理を自動で呼ばれる関数の中に突っ込んでおくことで実装できます。

■オートセーブしたい
・毎ターンの開始時
・イベントが進んだとき

■オートロードしたい
・ゲームを再開したとき

このゲームでのターンと言う概念は、「メイン画面で基地のリソースを拡充〜敵の襲撃〜戦闘を終えてメイン画面に戻る」これらのサイクルで1ターンという扱いになっています。

ターンの始まりに自動でセーブ処理を走らせるのであれば、

■ゲームを開始して初めてメイン画面にはいった。
■戦闘を終えてメイン画面に入った

こうすれば具合が良さそうです。逆に、これ以外のときにメイン画面に入る(戻る)ときはセーブが自動で行われると都合はよろしくありません。

なので、セーブ用の変数を使って状態を管理します。

// 毎ターンセーブの確認変数
pubric static int TurnSaved;
void Save()
{
    PlayerPrefs.SetInt("SaveEnergyNum",EnergyNum);
    PlayerPrefs.SetInt("TurnSaved",TurnSaved);

    PlayerPrefs.Save();
}


void Start()
{
    if(TurnSaved == 0)
    {
        TurnSaved = 1;
        Save();        
    }
}

(命名がガバガバ…!!)

自動で呼ばれるStart関数の中に、ターン開始時のセーブを行ったかどうかをチェックして、未セーブならセーブを行うという処理を追加しました。

セーブの際にチェック用変数が0から1になり、その状態で再びメイン画面に戻ってもセーブは行われないようになります。

一番最初のゲーム開始時は必ずチェック用変数が0のためセーブは行われます、戦闘終了時にこのチェック用変数を0に書き換えれば、その後メイン画面に戻ったときにも再びセーブが行われるという具合です。

ちなみに、この使い方はboolで良いのでは?と思った方もいるかもしれません。

実はこのターンセーブの状況もPlayerPrefsに保存しておきたいと考えていたものの、PlayerPrefsはbool型の変数に対応していないという問題がありました。

そのためInt型の変数でチェック用変数を宣言し、0と1でチェックすることで擬似的にbool型変数のような運用をしています。

実装してみた

エネルギー量の他にもセーブしておく要素を色々追加して、実際に実装してみたものがこちら。

メイン画面に戻ったとき以外に、イベント終了時にも個別でセーブ関数を呼ぶなどしています。

ゲームを終了して再び起動するとトップ画面から始まるようにしてあるので、トップ画面でセーブの有無をチェックし、セーブがあればそれをロードし、メイン画面に入った際にその内容を画面内のUIに渡して再現するようにしてあります。

というわけで

UnityのPlayerPrefsを使って外部アセットを使わず腕力でオートセーブ/ロード機能を作るという話でした。

こちらのゲームは11月いっぱいで作業を終了させる予定です。

が、この記事を書いているのが最終日。実はまだちょっと作業が残っています。AppStoreへのリリースに向けていくつか準備をすすめつつ、その流れでちょこちょこと作業を忍ばせて行こうと思います。

もう少し、優しく見守っていただけると幸いです…!


ここまで読んでいただきありがとうございました!

よろしければコメント、スキ、フォローお願い致します!

Twitterもやっていますのでよろしければこちらでも絡んでいただけると嬉しいです。
https://twitter.com/shiyoumasayume


他にも色々な記事を書いています。

作成中のDr.Holekingについての全記事はこちら

ゲーム開発の情報交換や相談の匿名チャットはこちら

プランナー向けの記事はこちら

はたらくクリエイターのためのプレイリストはこちら





よろしければサポートお願いします!いただいたサポートをモチベーションにまた活動を続けていきます