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.
-
Prepare Object: Place a 3D model (e.g., Sphere, Cube) that you want players to grab in the scene.
-
Add
Collider: Add a Collider component such asBox ColliderorSphere Colliderto the object. This is used to determine when the player's hand touches the object. -
Add
Rigidbody: Add aRigidbodycomponent 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, checkIs Kinematic. -
Add
VRCPickup: Add theVRCPickupcomponent to the object. This is the most important component for making an object "grabbable." -
Add
Udon Behaviour: Add anUdon Behaviourcomponent 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 asAutoHoldor selectUseCustomfor detailed settings.ExactGun/ExactGrip: WhenUseCustomis selected, assignTransforms 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
_EmissionColormay differ depending on the shader used. In the Standard shader,_EmissionColoris treated as aColortype, so usingSetColormay be more appropriate. Check the properties of the shader you're using.
Unity Setup
- Add a
Point Lightas a child object to the crystal object. Uncheckenabledin the initial state. - Set the crystal's material shader to one that supports Emission (e.g.,
Standard). - Assign
GlowingCrystal.csto the object's Udon Behaviour, and assign the child Light toCrystal Lightand the object's ownMeshRenderertoCrystal 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
- Add
VRCPickup,Rigidbody,Collider, andUdon Behaviourto the flashlight model. - Add a
Spot Lightcomponent to the tip and set it as theFlashlight. - Assign
SyncedFlashlight.csto the Udon Behaviour and drag & drop theSpot Lightonto theFlashlightfield.
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, andCollider. - Use events like
OnPickup,OnDrop, andOnPickupUseDownto 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(), andOnDeserialization().
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.