Persistence

Saving a player's progress, with two verbs instead of sixteen types and the one timing rule handled for you.

Updated 2026-09-08

VRChat can remember things about a player between visits. The API it gives you for that is a key-value store with a method per type: SetInt, GetInt, TryGetInt, and the same three again for each of sixteen types.

Three things about it go wrong quietly.

You have to remember which method wrote a key. Read "level" with GetString when it was written with SetInt and nothing complains — you get an empty string and carry on.

GetInt returns zero for a key nobody wrote, which is also what a saved zero looks like. A shop that gives newcomers a starting balance cannot tell a new player from one who spent everything.

Saved data is not there yet in Start. It arrives a moment after the player does. Read too early and you get defaults rather than an error, so the world behaves perfectly in the Editor, where there is nothing to restore, and greets a returning player as a stranger.

This package is two verbs and a base class:

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);
    }
}

The value decides the rest. Save.Set("name", "ada") stores a string and Save.Set("coins", 5) stores an integer, without you naming either. Reading takes the value you want when nothing is saved, which is the same value you would have written in the if below a TryGet — and having to write it is what separates "never saved" from "saved as nothing".

OnSaveReady runs at the only moment reading means anything. Put your loading there instead of in Start and the ordering stops being something you have to remember.

What is here

Save Set and Get, for every type VRChat stores
SaveBehaviour OnSaveReady, which runs when the data is real
PlayerObjects Finding the copy of an object that belongs to a player
Storage How much of a player's allowance the world has spent
Something went wrong Reload