【VRChat】Introduction to Pickup Objects: Creating Grabbable and Usable Items

Created: 2025-12-19

Implementing items that players can pick up and manipulate. VRCPickup component, OnPickup/OnDrop/OnPickupUseDown events, and state synchronization methods.

Overview

Pickup objects—items that players can actually pick up, wave around, use, and throw rather than just sit in the world—are crucial elements that dramatically deepen interaction with your world. Flashlights, balls, weapons, food—the applications are endless.

To implement pickup objects in UdonSharp, you use the VRCPickup component provided by the VRChat SDK along with related UdonSharp events.

This article explains everything from basic pickup object setup, to event handling when grabbing and releasing, to methods for synchronizing object state.

Step 1: Setting Up the VRCPickup Component

First, add the necessary components to the object you want players to be able to grab.

  1. Prepare Object: Place a 3D model (e.g., Sphere, Cube) that you want players to grab in the scene.

  2. Add Collider: Add a Collider component such as Box Collider or Sphere Collider to the object. This is used to determine when the player's hand touches the object.

  3. Add Rigidbody: Add a Rigidbody component to the object. This makes the object follow physics (gravity, etc.) and allows it to be thrown. If you only need grabbing and don't need physics, check Is Kinematic.

  4. Add VRCPickup: Add the VRCPickup component to the object. This is the most important component for making an object "grabbable."

  5. Add Udon Behaviour: Add an Udon Behaviour component to the object and assign the script described below.

Key VRCPickup Settings

  • InteractionText: Text displayed when aiming at the object (e.g., "Grab").
  • UseText: Text displayed while holding the object (e.g., "Use").
  • PickupOrientation: Sets the position/orientation the object will have in the hand when grabbed. Leave as AutoHold or select UseCustom for detailed settings.
  • ExactGun / ExactGrip: When UseCustom is selected, assign Transforms to fine-tune the grab position.

Pickup-Related UdonSharp Events

For objects with VRCPickup attached, the following UdonSharp events are automatically called in response to player grab/release/use actions.

  • OnPickup(): Called the moment an object is grabbed by a player.
  • OnDrop(): Called the moment an object is released from a player.
  • OnPickupUseDown(): Called the moment the Use button (VR trigger, etc.) is pressed while holding the object.
  • OnPickupUseUp(): Called the moment the Use button is released while holding the object.

Key Point: When a player Pickups an object, ownership of that object automatically transfers to that player. This allows the holding player to authoritatively change the object's state.

Example 1: Magic Crystal That Glows When Grabbed

A simple pickup object that lights up when a player picks it up and turns off when released.

Script: GlowingCrystal.cs

using UdonSharp;
using UnityEngine;

public class GlowingCrystal : UdonSharpBehaviour
{
    [Tooltip("Light component to control")]
    public Light crystalLight;
    [Tooltip("MeshRenderer's material emission to control")]
    public MeshRenderer crystalRenderer;

    private MaterialPropertyBlock propBlock;

    void Start()
    {
        propBlock = new MaterialPropertyBlock();
        // Start with light off
        SetGlow(false);
    }

    // Called when grabbed
    public override void OnPickup()
    {
        SetGlow(true);
    }

    // Called when released
    public override void OnDrop()
    {
        SetGlow(false);
    }

    private void SetGlow(bool isGlowing)
    {
        if (crystalLight != null)
        {
            crystalLight.enabled = isGlowing;
        }

        if (crystalRenderer != null)
        {
            crystalRenderer.GetPropertyBlock(propBlock);
            if (isGlowing)
            {
                // Enable Emission and set color to white
                propBlock.SetFloat("_EmissionColor", 1.0f);
            }
            else
            {
                propBlock.SetFloat("_EmissionColor", 0.0f);
            }
            crystalRenderer.SetPropertyBlock(propBlock);
        }
    }
}

Note: Shader property names like _EmissionColor may differ depending on the shader used. In the Standard shader, _EmissionColor is treated as a Color type, so using SetColor may be more appropriate. Check the properties of the shader you're using.

Unity Setup

  1. Add a Point Light as a child object to the crystal object. Uncheck enabled in the initial state.
  2. Set the crystal's material shader to one that supports Emission (e.g., Standard).
  3. Assign GlowingCrystal.cs to the object's Udon Behaviour, and assign the child Light to Crystal Light and the object's own MeshRenderer to Crystal Renderer.

Now, from the perspective of the player who grabs it, the crystal appears to glow. However, in this state, other players won't see it glowing. State synchronization is needed.

Example 2: Synced Flashlight

A gimmick where when someone picks up and turns on a flashlight, its lit state is synchronized across all players.

Script: SyncedFlashlight.cs

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;

public class SyncedFlashlight : UdonSharpBehaviour
{
    [Tooltip("The flashlight's light component")]
    public Light flashlight;

    [UdonSynced]
    private bool isLightOn = false;

    void Start()
    {
        // Reflect initial state
        UpdateLightState();
    }

    // When Use button is pressed while holding
    public override void OnPickupUseDown()
    {
        // Ownership was automatically transferred on Pickup, so not needed
        isLightOn = !isLightOn;
        RequestSerialization(); // Notify of state change
        UpdateLightState();
    }

    public override void OnDeserialization()
    {
        // Receive changes from other players and reflect state
        UpdateLightState();
    }

    private void UpdateLightState()
    {
        if (flashlight != null)
        {
            flashlight.enabled = isLightOn;
        }
    }
}

Unity Setup

  1. Add VRCPickup, Rigidbody, Collider, and Udon Behaviour to the flashlight model.
  2. Add a Spot Light component to the tip and set it as the Flashlight.
  3. Assign SyncedFlashlight.cs to the Udon Behaviour and drag & drop the Spot Light onto the Flashlight field.

Now, when someone grabs the flashlight and presses the Use button (trigger), the light turns on/off, and that state is synchronized to all players in the instance.

Summary

  • To make an object grabbable, the basic component set is VRCPickup, Rigidbody, and Collider.
  • Use events like OnPickup, OnDrop, and OnPickupUseDown to implement processing in response to player actions.
  • When an object is Pickuped, ownership automatically transfers to that player. This is a very important specification for implementing synced gimmicks.
  • To synchronize item state (ON/OFF, etc.), use the same sync pattern as previous gimmicks: combining [UdonSynced] variables, RequestSerialization(), and OnDeserialization().

Pickup objects are a powerful means of giving players the sensation of "touching the world." Apply these basics to create fun items that players can't resist picking up.