メリークリスマス!…と言いたいところですが、Unityエディタの前で 「再現手順:レベル50で特定のボスを倒す」 というチケットを眺めて絶望していませんか? チキンが冷める前に、そのデバッグ作業、HistoryTrackerで終わらせましょう。
🎄 HistoryTracker
ゲームデータ(永続保存データ)の保存/復元プラグイン
機能
- ゲームデータ(永続保存データ)の保存
- 保存したゲームデータの復元
- 見やすいUIで管理
- Unity Editorで保存したデータを実機へ出力
- スクリプトから自動保存構築
🎄 テストプレイで何度もレベル上げたりしてませんか?
DIコンテナを入れて、単体テストもばっちり。コードの設計は美しいはずなのに、いざプレイすると 「操作感がしっくりこない」「特定のタイミングだけバグる」… なんてこと、ありませんか?
ロジックの正しさはテストコードが保証してくれますが、「ゲームとしての手触り」や「予期せぬタイミングのバグ」は、やっぱり人間が触らないと見えてきません。だからこそ、実プレイの試行回数が重要です。でも、毎回最初からプレイするのは時間がもったいないですよね?
🎄 そんな時でも大丈夫。「そう、HistoryTrackerならね」
誤解させたくないのでストレートに言いますね。HistoryTrackerを使っても 「あなたは犠牲になります。」
結局のところ、最初の「再現データ」を作るための1回分のプレイは、誰かが汗をかいて行う必要があるからです。ですが、1度保存すればいつでも復元できるので、後に続くテスターや何度も試行する必要のあるプログラマーの助けになります。きっとあなたは感謝されるはずです。
UIから保存する
保存は簡単で、専用UIのSaveボタン から保存します。
復元
復元も簡単で、上記の一覧からいずれかを選択すると下記の詳細画面が開きます。
この画面のRestore Dataボタン から復元できます。
スクリプトから保存する
毎度、UIを開くのも面倒です。そういう時は任意のタイミングでスクリプトから保存すると便利です。
Hist.SaveHistory();
HistoryTrackerの保存タイミング例
- レベルアップ毎に保存
- ストーリー分岐前に保存
- エラーが発生した時に保存
- 特定のアイテムを購入した時に保存
🎄 デスマを避けて、聖夜を救え
単体テストをくぐり抜け、実機で発生したバグ。再現手順は複雑で、デベロッパーとしてあなたは嘆くでしょう。 しかし、HistoryTrackerがもたらすのは、「再現手順」ではなく、「バグが発生した瞬間のデータ」という動かぬ証拠です。複雑な準備なしに、原因究明という本質的な作業にすぐ取り掛かれます。
浮いた「時間」をどう使う?
テストプレイの繰り返しに費やしていた時間が削減されます。この時間を使ってあなたは何をしたいですか?
- 1時間早く帰宅し、家族とクリスマスディナーを楽しむ
- 浮いたデバッグ時間で、来年使う新しいアセットをじっくり品定めする
- テスト中に見つけた面白い挙動を、あえて「フィーチャー」 として採用するか検討する
HistoryTrackerは、ただのセーブ&ロードツールではありません。「開発者の自由な時間」を確保し、ひいては「ゲームのクオリティを上げるための時間」 を生み出す、時間管理ツールなのです。
🎄 【おまけ】 HistoryTracker 実装の裏側
Advent Calendarの記事なので技術的な話も少し。
1. データの実機ビルドにおける葛藤
HistoryTrackerにおいて是非とも実装したかったのが、「Unity Editorで生成したゲームデータを、実機上でも復元する機能」 です。これを実現するには StreamingAssets を利用するのが定石ですが、ある条件をクリアする必要がありました。
『 StreamingAssetsに配置したデータは使われなくてもビルドに含まれる 』
Unityは通常、ビルドに使用しているリソースのみをパッケージングしますが、例外として StreamingAssets または Resources フォルダ内のデータは、無条件にすべてのビルドに含まれてしまいます。 したがって、「機能を使わない場合はビルドに含めたくない」という要件を満たすための対策が必要でした。
検討の結果、普段は Assetsフォルダの階層外 にゲームデータを保存しておき、必要な場合のみ以下の処理を行うように実装しました。
- ビルド開始時に
StreamingAssetsへデータをコピー - ビルド完了後にコピーしたデータを削除
データはGit管理できる?
プロジェクトのルートに保存するので、特別な設定をしていなければGit管理に含まれます。
実際のコード
2. UI Prefabの参照はどうする?
詳細を表示するUIをPrefabで作成しましたが、次に「どうやって参照を持たせるか」を考えなければいけません。いくつかの手法がありますが、それぞれにデメリットがあります。
| 手法 | メリット | デメリット |
|---|---|---|
| Inspectorからアタッチ | 一番楽 | 参照が残りやすく、不要な場合もビルドに含まれるリスクが高い |
| Resources | 動的ロードが可能 |
StreamingAssets同様、無条件でビルドに含まれてしまう |
| Addressables | メモリ管理が優秀 | ビルドに含まれるリスクに加え、このプラグインのために導入してもらうのは気が引ける |
解決策:環境に応じたロードとResourcesの一時利用
上記を踏まえた結果、環境によってロード方法を切り替えることにしました。
- Unity Editor: AssetDatabase.LoadAssetAtPath でロード
- 実機: Resources.Load でロード
ここでも前述と同じように、必要な場合のみビルド時にコピーし、ビルド後に削除するように実装しました。
また、Resources はメモリ管理が難しいため、画像を一枚も使わず軽量なPrefabになるように工夫しています。
実際のコード
3. AndroidではStreamingAssets内のデータは圧縮されている
Androidの場合、ビルドされたapk(またはaab)は圧縮されています。そのため、StreamingAssets 内のファイルパスを直接指定しても、アクセスできずエラーとなります。
これに対応するため、Androidでは UnityWebRequest.Get を用いてロードします。
実際のコード
🎄 最後に
去年に引き続きプラグインを公開しました。
誰かにとって嬉しいクリスマスプレゼントになれば嬉しいです。
メリークリスマス 🎄
良いクリスマスと新年を 🎉
インストール方法などの詳細はリポジトリで

