Rimworldでのデータの保存と読み込み

MOD製作者ならほぼ全ての人が熟知しているであろうRimworldにおけるデータの保存と読み込みについての話。


indexへ

参考: * https://spdskatr.github.io/RWModdingResources/saving-guide.html

■Rimworldでのデータの保存

MODつくるとセーブしたデータがロードすると反映されていなくてにゃーんとなることがままあるが、それらはだいたい保存をしていないからである。

なのでRimwroldにおいてはデータセーブとロードは必須なのだが、解説記事があんまりないしピンと来ないものなので書く。

■大前提の話

RimworldではIExposableに実装されているExposeDataがSave・Load時に読まれて、その中のScribeほにゃ.Lookで値の保存・読み込みが実行され、セーブデータやModSettingに保存されている値を反映させられる。

なお、MOD導入時などの値が見つからない場合は初期値(場合によってはnull)か defaultValue の値が読み込まれる。

ExposeData

IExposableというインターフェイスのメソッド。

Rimworldでは、セーブとロード時にこのメソッドが呼ばれるので、IExposableを継承して、このメソッド内にデータを保存する処理を書けばいい。

    public override void ExposeData()
      {
        //ここの保存処理を書く
      }

Scribeを用いたデータの保存

前節で保存処理を書く場所は書いたので、実際に値を保存する方法を書く。

Rimworldでは、 保存したいデータの種類に対応した Scribe_ほにゃ クラスの、void Look(...)メソッドを使用して保存・読み込みをする。

lookModeについて

Scribe_Collectionsなどでkeyやvalueを保存する際に、引数として〇〇LookModeというのがある。これは保存するデータによってそれぞれ指定するlookmodeの値が異なる。

保存時・読み込み時特有の処理

保存・読み込んだときにだけやりたい処理がある場合とかは、Scribe.modeの値をみて処理を変える。

保存時にはLoadSaveMode.Savingが1度だけ実行される。 読み込み時は、複数回ExposeDataが以下の順序で呼ばれる。

  1. LoadingVars:値の読み込み。
  2. ResolvingCrossRefs:参照の読み込み。1.で読み込んだ値を使用して読み込む
  3. PostLoadInit:事後処理

上記をまとめた使い方例

  public override ExposeData(){
    if(Scribe.mode == LoadSaveMode.Saving){
        //保存時に不要なデータをlistから削除しておく
        DeleteNonePawn(list);
    }
    else if(Scribe.mode == LoadSaveMode.LoadingVars){
        // 読み込み時にこのクラスで使用する変数を初期化する
        // 読み込みとかは下のScribe_ほにゃ.Lookですること。あくまでLookで読み込めない/読み込む必要がない値の初期化。
        // Lookの引数で指定もできるので無理に書く必要はない
        tmp = new List<Pawn>();
    }

    // saveDataにPawnCountという名前で保存し、
    // saveDataからPawnCountの値を探し、見つかればそれで、見つからなかったら0で count を初期化する。
    Scribe_Values.Look(ref count, "PawnCount", 0);

    Scribe_Collections.Look(ref pawnList, "PawnList", LookMode.Def, tmp);
  }

みたいな感じで。

■保存するデータの単位

どこでデータを保存するかの話。 全然調べていないけど、多分 下の2つくらいしか使わないと思う。

セーブデータ単位

要は、別のセーブデータを読み込んだ際に別のデータを読み込むかどうかの話。 下のWorldComponentとかMapComponentをOverrideしたのをプロジェクトに追加しておいて、ExposeDataで保存・読み込みしておけば問題ない。

ゲーム単位

セーブデータに関わらず読み込みたい、例えばConfigのMod設定とかでいじれる値とか。 下のModSettingsをOverrideしたのを以下略。

上記をまとめた使い方例

  public classs TestModSetting : ModSettings
  {
    // なんかMOD独特の設定。
    private float count;

    public override void ExposeData(){
        //上と同じく読み書き。
        Scribe_Values.Look(ref count, "count", 0);
    }

  }