Skip to main content

Player Object

GameObjects with the VRCPlayerObject component are treated as Player Objects. Player Objects are automatically instantiated once for each player that joins, providing each player with their own copy of that GameObject, its UdonBehaviours, other components, and children. Each Player Object is instantiated with the same position, rotation, scale, and parent as the original.

Known bug

Currently, ClientSim does not instantiate Player Object at the same position, rotation, scale, and parent as the original.

The most recent network-synchronized state of the Player Objects is saved on VRChat's servers and restored whenever the player reenters the world. When all of that player's Player Objects have been restored, the OnPlayerRestored event is triggered for everyone, including the owner of the Player Object.

Player Objects maintain their inspector references after being instantiated, and it's safe for player object components to have references to the scene component. It is not safe for scene components to reference, modify, or reparent the original Player Object directly! Use Networking.GetPlayerObjects instead. Player Objects returned by GetPlayerObjects are safe to reference, modify, or reparent.

All networked behaviours within a Player Object can only ever be owned by the player that is associated with that Player Object. They can never transfer ownership. This makes them an excellent tool for avoiding players interrupting each other, as they can be confident that they always have authority on their own objects.

If you have a Player Object with an UdonBehaviour that has some synchronized variables, and you want to persist those variables across instances, then you must add the VRCEnablePersistence component to the object with the UdonBehaviour. You can have multiple independent objects within a single player object where some have persistence, and others do not.

Events

EventOutputNotes
OnPlayerRestoredVRCPlayerApi playerTriggered after all of a VRChat player's persistent data has been loaded.
Watch out for timing issues

Wait for the OnDeserialization event before using a Player Object's persistent data. Or wait for the OnPlayerRestored to guarantee that all of a player's Player Object have finished loading.

In the Start event of a Player Object, its ownership is guaranteed to be correct. However, its synced data may not be correct yet. It may take some additional time before a Player Object receives data. If you change synced data on a Player Object too early, it will be overwritten when the persistent data is received.

Methods

Player object methods are in the VRC.SDKBase.Networking namespace.

FunctionInputOutputNotes
GetPlayerObjectsVRCPlayerApi targetGameObject[] objectsReturns an array of all the Player Objects associated with the player provided

Examples

Finding a custom script on a Player Object

This example automatically looks through all player objects and finds a specific component that you're looking for. Replace CustomPlayerObjectScript with the type of component that you want to find.

public CustomPlayerObjectScript Find(VRCPlayerApi player)
{
var objects = Networking.GetPlayerObjects(player);
for (int i = 0; i < objects.Length; i++)
{
if (!Utilities.IsValid(objects[i])) continue;
CustomPlayerObjectScript foundScript = objects[i].GetComponentInChildren<CustomPlayerObjectScript>();
if (Utilities.IsValid(foundScript)) return foundScript;
}
return null;
}

Gotchas

  • In the Start event of a Player Object, its ownership is guaranteed to be correct, but its synced data may not be correct. It may take some additional time after Start before the data is received and OnDeserialization is called. If you set synced data on a Player Object too early, it will be overwritten when the persistent data is received. Wait until after the OnPlayerRestored event to read or write Player Object data.