【DAY83】Unityのセーブ機能を考える
Unityでのセーブ処理とJavaScriptとの違い
最近、GitHub Pagesで公開しているJavaScript製のミニゲームにlocalStorage
を使ったセーブ機能を実装した。これにより、ユーザーのブラウザ単位で進行状況を保存でき、ページを再読み込みしてもデータが残る仕組みが完成した。
しかし、これと全く同じことをUnityでやろうとすると、少し勝手が違う。Unityでは、標準で用意されているPlayerPrefs
というクラスを使ってローカルにデータを保存できる。ただし、PlayerPrefs
はあくまで小規模なデータ向けで、例えばハイスコアや設定値、進行ステージのインデックス程度が適している。
// ステージ番号を保存
PlayerPrefs.SetInt("stage", 3);
PlayerPrefs.Save();
// ステージ番号を読み込み
int stage = PlayerPrefs.GetInt("stage", 0);
保存先はプラットフォームごとに異なり、Windowsではレジストリ、AndroidやiOSではアプリごとのサンドボックス領域に保存される。これはJavaScriptのlocalStorage
と似て非なるもので、例えばスマホとPCでデータ共有は基本的にできない。
一方で、JavaScriptのlocalStorage
は以下のように非常に手軽で、文字列であればなんでも保存できる。
// ゲームデータ保存
localStorage.setItem("score", "1200");
// 取得
const score = localStorage.getItem("score");
Unityで本格的なセーブ機能を作るには?
PlayerPrefs
だけでは足りないと感じる場合、UnityではJSONファイルを用いた独自のセーブシステムを構築するのが定番だ。これにより、ゲームの状態(キャラクター情報、アイテム、座標など)を構造的に保存できる。
[System.Serializable]
public class SaveData {
public int level;
public float health;
}
void SaveGame() {
SaveData data = new SaveData();
data.level = 5;
data.health = 78.5f;
string json = JsonUtility.ToJson(data);
File.WriteAllText(Application.persistentDataPath + "/save.json", json);
}
このやり方であれば、Application.persistentDataPath
を利用して、プラットフォームごとに適切な保存ディレクトリにデータを書き出すことができる。セキュリティやアクセス権の面でも安全性が高い。
JavaScriptとの棲み分け
JavaScriptゲームでは、環境が完全にブラウザ上に限定されているため、セーブデータは軽量かつセッション的な使い方が主となる。一方、Unityではモバイル、PC、コンソールなど多様な環境で動作するため、セーブ機能もより堅牢で柔軟な設計が求められる。
また、UnityのWebGLビルドではPlayerPrefs
の実体も内部的にはIndexedDB
を使用しているため、実はJavaScriptと似た構造を取っている。しかし、WebGLではファイルの読み書きに制限が多く、通常のJSON保存手法はそのまま使えない点に注意が必要だ。
まとめ
GitHub Pagesに公開しているJavaScriptゲームで実装したlocalStorage
セーブは、手軽で良い方法だったが、Unityでは環境に応じたセーブ方式を選ぶ必要がある。特にクロスプラットフォーム展開を視野に入れるなら、ファイルベースのJSON保存、クラウド連携など、拡張性のある設計が重要になる。Unityでのセーブは単なる「保存」ではなく、設計思想そのものが問われるポイントだと感じた。
Discussion