永続化

プレイヤーの進行状況の保存を、16 種類のメソッドではなく 2 つの動詞で。タイミングの落とし穴も引き受けます。

更新日 2026-09-08

VRChat は、プレイヤーについての情報を訪問のあいだ覚えておくことができます。そのために用意されている API は型ごとにメソッドが分かれたキーと値のストアで、SetIntGetIntTryGetInt があり、同じ 3 つが 16 の型それぞれに用意されています。

そこには静かに壊れるものが 3 つあります。

どのメソッドがそのキーを書いたかを覚えておく必要があります。 SetInt で書いた "level"GetString で読んでも何も言われません。空の文字列が返り、そのまま進みます。

誰も書いていないキーに対して GetInt はゼロを返します。 これは保存されたゼロと見分けがつきません。新規プレイヤーに所持金を配る店は、初めての人と使い切った人を区別できないことになります。

Start の時点では保存データはまだ届いていません。 プレイヤーが入ってきた少しあとに届きます。早く読んでもエラーにはならず既定値が返るので、復元するものが何もない Editor では完璧に動き、進行状況を持った本物のプレイヤーを初めての人として迎えます。

このパッケージは 2 つの動詞と 1 つの基底クラスです。

public class Shop : SaveBehaviour
{
    private int coins;

    public override void OnSaveReady()
    {
        coins = Save.Get("coins", 100);
    }

    public void Buy(int price)
    {
        coins = coins - price;
        Save.Set("coins", coins);
    }
}

あとは値が決めてくれます。Save.Set("name", "ada") は文字列を、Save.Set("coins", 5) は整数を保存します。どちらの型かをあなたが名指しする必要はありません。読み取りには「何も保存されていなかったときの値」を渡します。これは TryGet の下の if に書いたはずの値そのもので、それを必ず書かせることが「一度も保存されていない」と「ゼロとして保存された」を分けています。

OnSaveReady は、読むことに意味がある唯一の瞬間に走ります。読み込みを Start ではなくそこに置けば、順序を覚えておく必要はなくなります。

入っているもの

Save Set と Get。VRChat が保存できるすべての型に
SaveBehaviour データが本物になった瞬間に走る OnSaveReady
PlayerObjects あるプレイヤーのものであるコピーを見つける
Storage そのプレイヤーの容量をワールドがどれだけ使ったか
問題が発生しました 再読み込み