ゲームの状態をどのように保存しますか?


27

ゲームの状態を保存および再開するためにゲームプログラマーが従う手順は何ですか?ファイル/マッピングのような。タワーディフェンスゲーム用に保存したいのですが、Unity3Dゲームエンジンを使用しています。

回答:


16

私は通常、メモリのスナップショットの観点では考えていませんが、セッション間で保存する必要がある値のリストを作成し、それらの値を外部ファイルに保存するだけです。

これはもちろん特定のゲームのニーズに依存しますが、通常は現在のレベルの状態(つまり、すべての敵がどこにいるのか、彼らの健康状態など)を保存してから、プレイヤーのレベルのような高レベルのものを保存しますすでに完了しています。


3
+1それが私がやる方法です。必要なものをバイナリファイルに書き込みます。そして、何か新しいものを追加する必要がある場合は、最後に追加して、古い保存ファイルを壊さないようにします。
カオス技術者

これは、古い保存ファイルを壊さないことに関する良いヒントです。ただし、最後にデータを追加することは、データの保存方法とは無関係です。辞書をシリアライズ/デシリアライズすることでそれを行いますが、そのデータ構造では順序は関係ありません。
冗談

(基本的には、私のオブジェクト辞書であるとヨナスの答えのコード、)
jhocking

10

この答えはUnity3d固有のものです。
Unityでは、ほとんどのクラスはシリアル化可能です。つまり、完全なUnityオブジェクトをディスクにストリーミングできることを意味します。次のUnityScript-Codeは、オブジェクトをシリアル化し、ディスクに保存して再度ロードする方法です(ロード後にオブジェクトをキャストする必要があります)。

import System;
import System.IO;
import System.IO.Stream;
import System.Runtime.Serialization;
import System.Runtime.Serialization.Formatters.Binary;

class SaveLoad {
        public static function SaveFile(filename:String, obj:Object):void {
                try {
                        Debug.Log("Writing Stream to Disk.", SaveLoad);
                        var fileStream:Stream = File.Open(filename, FileMode.Create);
                        var formatter:BinaryFormatter = new BinaryFormatter();
                        formatter.Serialize(fileStream, obj);
                        fileStream.Close();
                } catch(e:Exception) {
                        Debug.LogWarning("Save.SaveFile(): Failed to serialize object to a file " + filename + " (Reason: " + e.ToString() + ")");
                }
        }

        public static function LoadFile(filename:String):Object {
                try {
                        Debug.Log("Reading Stream from Disk.", SaveLoad);
                        var fileStream:Stream = File.Open(filename, FileMode.Open, FileAccess.Read);
                        var formatter:BinaryFormatter = new BinaryFormatter();
                        var obj:Object= formatter.Deserialize(fileStream);
                        fileStream.Close();
                        return obj;
                } catch(e:Exception) {
                        Debug.LogWarning("SaveLoad.LoadFile(): Failed to deserialize a file " + filename + " (Reason: " + e.ToString() + ")");
                        return null;
                }       
        }
}

2
C#を使用するほかに、PlayerPrefsも使用する必要があります。これらはクロスプラットフォームであり、Web / iOS / AndroidではIOを実行できません。unity3d.com/support/documentation/ScriptReference/…(素敵なサンプル!)
TJHeuvel

PlayerPrefsは柔軟性が非常に低く、クロスプラットフォームであり、単一の値または無関係の値を格納するのに最適です。ただし、Windows PlayerPrefsはレジストリ、プレーンテキストに保存されます。
ジョナス

7
既にシリアル化している場合は、Stringにシリアル化してPlayerPrefsに保存してください。確かに柔軟性は劣りますが、クロスプラットフォームゲームの唯一のソリューションです。
-TJHeuvel

2
PlayerPrefsは設定のような小さなデータを格納するための素晴らしいですが、全体のセーブデータのために、あなたはApplication.persistentDataPath使うべきdocs.unity3d.com/ScriptReference/...を
jhocking

2
@TJHeuvel:あなたが最も確かに、モバイル上でIOを行うことができます「あなたがウェブ/ iOS版/ Android上でIOを行うカント」
はPrzemyslawWrzesiński

2

TDの場合、おそらく波の間だけを保存します。そうすれば、あなたが考えなければならないのは塔だけです。レベルに10分以内のレベルに自動保存ポイントをいくつか入れますが、それより少ない方がおそらく望ましいでしょう。

もちろん、レベルが十分に短い場合は、キャンペーンのステータスのみを保存できます。


1

ゲームの現在の状態を参照するとき、保存の瞬間のメモリスナップショットを参照しています。HDDに保存するデータからそれを再作成できる必要があります。

永続的である必要があるデータを持つすべてのクラスをシリアル化し、HDDにダンプするだけで、メモリダンプを実行するのが最も簡単です。これに伴う問題は、クラスを変更すると、シリアル化された値の数/タイプが変更され、古い保存が破損することです。また、すべてを保存しているため、読み込み時間が長くなります。シリアライザ/ IDEが使用する属性システムで現在の「メモリスナップショット」を再構築するために実際に必要な個々のフィールドをマークする方が効率的です。次に、保存したデータから「メモリスナップショット」を再構築します。

また、Unityを使用したことがないため、Unityに何かが組み込まれている場合があります。しかし、これは典型的なアプローチです。


状態をファイルに保存する必要があるということですか?
Syed

1
@Syedはい、アプリの状態はメモリに保存されないため、一日の終わりに何らかの種類のファイルに書き込む必要があります。特にUnityを使用すると、ファイル全体の読み取り/書き込みを回避したい場合は、PlayerPrefsクラス(Windowsでは実際にレジストリに保存されていると思います)を使用できます。
テトラッド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.