Player objects

A whole object that belongs to each player and is saved with them, and how a script finds the right copy.

Updated 2026-09-08

Save is a drawer of labelled values. A player object is a whole GameObject that VRChat gives to every player and remembers for them.

It suits different things. An inventory, a tool somebody carries, a settings panel: anything with structure, anything large, anything that changes often. It also has its own separate allowance, so it does not compete with your saved values for room.

Setting one up

Put the object in your scene and add a VRCPlayerObject component. Add VRCEnablePersistence as well and its synced variables are remembered between visits.

VRChat then does something that catches people out: your object becomes a template. It is switched off and left where it is, and every player gets their own copy of it. The copy is what runs. Nothing in the scene can point at a copy, because the copies do not exist until people arrive.

Finding the right copy

So a script cannot hold a reference to the instance it wants. It holds the template — which is the only thing you can drag into the inspector — and asks which copy belongs to whom:

public Inventory template;   // drag the template in

public override void OnSaveReady()
{
    Inventory mine = PlayerObjects.Mine(template);
    mine.Add("hat");
}

For somebody else's:

Inventory theirs = PlayerObjects.Of(player, template);

PlayerObjects.Mine() with no argument hands back every object belonging to the player at this client, if you would rather look through them yourself.

Ownership

Players own their own copies and that cannot be transferred. It is the rule that stops somebody walking off with another person's things, and it means you never have to request ownership of a player object before changing it.

The same timing rule

Player objects load their saved values at the same moment saved values arrive, so OnSaveReady is where to read them too. Reading in Start gives you whatever the object looked like before its data landed.

Room

Roughly 100 KB per player for saved values, and another 100 KB for player objects. Going over does not stop the world — VRChat logs an error and stops saving, so it keeps running and quietly stops remembering.

public override void OnPersistenceUsageUpdated()
{
    int used = Storage.SaveUsed();
    int limit = Storage.SaveLimit;
}

Read those numbers here and nowhere else. They are recalculated occasionally rather than maintained, and before the first calculation they read zero — which means "not counted yet", not "no room". Overriding OnPlayerDataStorageWarning is how you hear about a player getting close while there is still time to do something.

Something went wrong Reload