【VRChat】Complete Guide to Player Events: Detecting Join, Leave, and Respawn

Created: 2025-12-19

Events for detecting player state changes in worlds. Implementation methods for OnPlayerJoined/Left, OnPlayerRespawn, OnAvatarChanged, and pickup-related events.

Overview

VRChat worlds only have meaning when players exist in them. Making gimmicks activate when players join the world or take specific actions within it makes the world more dynamic and attractive.

UdonSharp provides numerous events for detecting various happenings related to players. This article picks out the most important of these player events and explains their usage and application examples.

These events often take a VRCPlayerApi object as an argument, through which you can access information about the player who triggered the event (name, ID, etc.).

1. Player Join and Leave

Events for detecting players entering and leaving a world are fundamental to social features and game management.

OnPlayerJoined(VRCPlayerApi player)

  • Execution Timing: Called on all players' clients in the instance when a new player joins the instance and loading is complete.
  • Argument: VRCPlayerApi object of the joining player.
  • Main Uses:
    • Displaying join logs (e.g., "Taro has joined").
    • Updating player lists.
    • Counting game participants and starting the game when capacity is reached.

OnPlayerLeft(VRCPlayerApi player)

  • Execution Timing: Called on all remaining players' clients in the instance when a player leaves the instance.
  • Argument: VRCPlayerApi object of the leaving player.
  • Main Uses:
    • Displaying leave logs.
    • Removing names from player lists.
    • Electing a new master if the game master leaves.
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;

public class PlayerJoinLeaveLogger : UdonSharpBehaviour
{
    public override void OnPlayerJoined(VRCPlayerApi player)
    {
        // Only display message if the joining player is not yourself
        if (player.isLocal)
        {
            Debug.Log("Welcome to the world!");
        }
        else
        {
            Debug.Log($"{player.displayName} has joined the world.");
        }
    }

    public override void OnPlayerLeft(VRCPlayerApi player)
    {
        // Check if player doesn't exist (error prevention)
        if (player == null) return;

        Debug.Log($"{player.displayName} has left the world.");
    }
}

2. Player Death and Respawn

For obstacle courses and combat games, you need to handle player death (falling, etc.) and respawn (revival).

OnPlayerRespawn(VRCPlayerApi player)

  • Execution Timing: Called only on the respawning player's own client when the player clicks "Respawn" from the VRChat menu, or falls below the respawn altitude set in the VRC Scene Descriptor.
  • Argument: VRCPlayerApi object of the respawning player.
  • Main Uses:
    • Resetting health, score, and held items.
    • Granting temporary invincibility on respawn.

Important: Calling VRCPlayerApi.Respawn() from a script does NOT fire the OnPlayerRespawn event. If you need additional processing when respawning from a script, design it to execute that processing directly just before or after calling Respawn().

// Example script for managing player health
public class PlayerHealth : UdonSharpBehaviour
{
    private int health = 100;

    // Custom event called when player takes damage
    public void TakeDamage(int damage)
    {
        health -= damage;
        if (health <= 0)
        {
            // Respawn if health drops to 0 or below
            // Note: Respawn() doesn't fire OnPlayerRespawn,
            // so call reset processing directly
            ResetHealth();
            Networking.LocalPlayer.Respawn();
        }
    }

    // Processing to reset health
    private void ResetHealth()
    {
        health = 100;
        Debug.Log("Health fully recovered.");
    }

    // Called on menu respawn or fall
    public override void OnPlayerRespawn(VRCPlayerApi player)
    {
        ResetHealth();
    }
}

3. Avatar-Related Events

You can also detect changes related to avatars used by players.

OnAvatarChanged(VRCPlayerApi player)

  • Execution Timing: Called only on that player's own client when a player changes their avatar.
  • Argument: VRCPlayerApi object of the player who changed avatars.
  • Main Uses:
    • Enabling/disabling gimmicks that only work with specific avatars.
    • Measuring avatar height (scale) and adjusting gimmick behavior accordingly.

OnAvatarEyeHeightChanged(VRCPlayerApi player, float eyeHeight)

  • Execution Timing: Called on all players' clients in the instance when a player's avatar eye height changes (during calibration, etc.).
  • Main Uses:
    • Adjusting UI position according to player height.

4. Pickup (Grabbing Objects) Events

Events also fire when players grab or release objects with the VRCPickup component attached.

OnPickup()

  • Execution Timing: Called the moment a player grabs this object.

OnDrop()

  • Execution Timing: Called the moment a player releases this object.

OnPickupUseDown() / OnPickupUseUp()

  • Execution Timing: Called the moment the Use button (VR trigger, etc.) is pressed (UseDown) / released (UseUp) while holding the object.
  • Main Uses: Implementing items operated while held, like gun triggers or flashlight switches.
// Example flashlight script
public class Flashlight : UdonSharpBehaviour
{
    public Light flashlight;

    // Toggle light when trigger is pulled while holding
    public override void OnPickupUseDown()
    {
        flashlight.enabled = !flashlight.enabled;
    }
}

Summary

  • By using player-related events, you can create interactive gimmicks that respond to player actions and state changes.
  • OnPlayerJoined / OnPlayerLeft detect player arrivals and departures and execute on all players.
  • OnPlayerRespawn detects player respawns and executes only on the player themselves.
  • OnAvatarChanged detects avatar changes and executes only on the player themselves.
  • OnPickup family of events detect grabbing, releasing, and using objects.
  • Many of these events take a VRCPlayerApi object as an argument, allowing you to get information about who triggered the event.

By mastering these player events, you can move from gimmicks that simply move to creating more immersive world experiences that are aware of player presence.