Building World-Space UI: Calling Udon from Buttons and Sliders

Created: 2026-09-08Last updated: 2026-09-09

Putting buttons and a slider on a World Space Canvas to build a settings panel that drives Udon. Covers the components required to make it pressable in VRChat, and why it doesn't respond.

You want visitors to be able to adjust the BGM volume, or set the lighting to their taste.

Building a settings panel like that needs UI floating inside the world. Follow Unity's standard steps, though, and you often end up with UI that's pressable in the editor but unresponsive in VRChat.

This article builds a panel that's reliably pressable in VRChat, calling Udon logic from a button and a slider.

Operating a panel floating in the air with a laser pointer

What You'll Learn

  • The four components that make UI pressable in VRChat
  • The steps for calling an Udon method from a button
  • How to receive a slider's value
  • Causes of unresponsive UI, in order of frequency

Start from having tried methods and custom events.

Sponsored


Four components are required to make it pressable

UI built in Unity is clickable with the mouse in editor Play. Upload it to VRChat and it isn't.

That's because the component connecting VRChat's laser pointer to Unity UI is missing.

Canvas, Graphic Raycaster, VRC Ui Shape, and EventSystem together are what make it pressable

These four are needed.

ComponentRoleWhere it goes
Canvas (World Space)The panel holding the UIYou create it
Graphic RaycasterDecides whether the pointer hitSame object as the Canvas (added automatically)
VRC Ui ShapeConnects VRChat's pointer to Unity UISame object as the Canvas (you add it)
EventSystemThe receiver that distributes clicksExactly one per scene

The most common failure is forgetting VRC Ui Shape. Without it you get the confusing state of pressable in the editor, unpressable in VRChat.

Adding it brings a Box Collider automatically. That Collider becomes the touchable surface, so you don't need to add your own.

Also, leave the layer at Default. Don't set it to UI. The VRChat client's own menu uses the UI layer, so putting it there stops the world's pointer from hitting it.

Exactly one EventSystem per scene. It's added automatically the first time you create UI. Multiple ones break things, so check that they haven't multiplied.

Sponsored

Hands-On: Build a volume and lighting panel

Build a panel with a slider for BGM volume and a button for toggling the lighting.

1. Place the panel

Create a "UI → Canvas" and name it ControlPanel.

FieldSetting
Render ModeWorld Space
Position(0, 1.4, 2.8)
Rotation(0, 180, 0)
Width / Height400 / 300
Scale(0.005, 0.005, 0.005)
LayerDefault
In World Space one unit is one meter, so you adjust with Scale

Scale is small because a World Space Canvas treats one unit as one meter. Width 400 gives you a 400m panel. At 0.005 you get a realistic 2m by 1.5m.

Add VRC Ui Shape via "Add Component." Now it's pressable.

Confirm there's an EventSystem in the Hierarchy too. If not, it's added automatically when you create a UI element.

2. Place the slider and button

Right-click ControlPanel and add the following.

  • Add a "UI → Slider," name it VolumeSlider, and place it in the panel's upper half
  • Add a "UI → Button - TextMeshPro," name it LightButton, and place it in the lower half

Set the Slider's Min Value to 0, Max Value to 1, and Value to 0.12, since it'll serve as the BGM volume.

Set the button's text to "Toggle lighting."

3. Write the code that receives the input

Create PanelController with "Create Empty" at (0, 0, 0).

In Assets/Scripts, choose "Create → U# Script" and make RoomControlPanel.

using UdonSharp;
using UnityEngine;
using UnityEngine.UI;

[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class RoomControlPanel : UdonSharpBehaviour
{
    [SerializeField] private AudioSource bgm;
    [SerializeField] private Light roomLight;
    [SerializeField] private Slider volumeSlider;

    private bool lightOn = true;

    private void Start()
    {
        ApplyVolume();
        ApplyLight();
    }

    // Called from the slider. No arguments, so read the value yourself
    public void OnVolumeChanged()
    {
        ApplyVolume();
    }

    // Called from the button
    public void ToggleLight()
    {
        lightOn = !lightOn;
        ApplyLight();
        Debug.Log("[ControlPanel] light=" + lightOn);
    }

    private void ApplyVolume()
    {
        if (bgm == null || volumeSlider == null) return;
        bgm.volume = volumeSlider.value;
    }

    private void ApplyLight()
    {
        if (roomLight != null) roomLight.enabled = lightOn;
    }
}

The important part is that methods called from UI are public and take no arguments.

The slider's value doesn't arrive as an argument. The method reads volumeSlider.value itself. That's why it holds a reference to the slider.

4. Wire the UI to Udon

Add a Udon Behaviour to PanelController and set RoomControlPanel. Assign BGM, Room Light, and Volume Slider.

Now set up the calls from the UI side.

How button and slider input flows into Udon methods

For the button:

  1. Select LightButton and press + under On Click () in the Inspector
  2. Drag PanelController from the Hierarchy into the empty field
  3. Choose UdonBehaviour → SendCustomEvent from the dropdown on the right
  4. Type ToggleLight into the text field below

For the slider:

  1. Select VolumeSlider and press + under On Value Changed (Single)
  2. Drag PanelController in
  3. Choose UdonBehaviour → SendCustomEvent
  4. Type OnVolumeChanged into the text field

The method name is typed as text, so a misspelling means nothing happens. Compare it character by character with the method name in the code.

5. Confirm

Press Play and operate the panel.

ActionExpected result
Press the buttonThe lighting goes off. Console shows light=False
Press againIt comes on
Move the sliderThe BGM volume changes
Operate it from a distanceToo far and it doesn't reach

Don't relax just because it works in ClientSim. A forgotten VRC Ui Shape only shows up in actual VRChat. Check with Build & Test too.

Causes of unresponsive UI

Listed in order of frequency.

Three things to suspect when it won't press
  1. VRC Ui Shape isn't attached → Add it to the same object as the Canvas. When it's pressable in the editor but not in VRChat, start here
  2. The layer is UI → Set it back to Default
  3. No EventSystem, or several → Keep exactly one per scene
  4. Graphic Raycaster is gone → Check that it's on the same object as the Canvas
  5. The method name is misspelled → Compare the text in SendCustomEvent against the code
  6. The Canvas scale is extreme → Too large and the collision goes off. Aim around 0.005

If you change the Canvas size afterwards, the Collider added by VRC Ui Shape can be left at the old size. Remove and re-add it in that case.

Sponsored

Bonus: Good to Know Up Front

  • Controls differ between VR and desktop: VR uses the controller's laser, desktop uses the pointer at screen center. Size things so both can press them. Buttons that aren't too small are a kindness
  • This is local logic: Both the volume and the lighting change only on the operator's screen. Volume being per-person is the kinder design, so that's correct. Things you want shared go to networking basics
  • Settings can be remembered for next time: A volume setting can carry over to the visitor's next visit. Covered in saving volume with PlayerData
  • Watch the panel height: People playing seated have eye level down around 1.1m. A panel placed too high can't be operated from a seat
  • It's useful all over: Volume control in social worlds, difficulty selection in games, language switching in exhibition worlds, lighting control at event venues. All built the same way

Summary

World-space UI only works with four components together.

  • Canvas, Graphic Raycaster, VRC Ui Shape, EventSystem
  • The layer is Default. Not UI
  • In World Space, one unit is one meter. Adjust with Scale
  • Buttons call methods by name with SendCustomEvent. No arguments

The question to ask after building it is: "Was it pressable in VRChat?" Being pressable in the editor proves nothing.

To remember settings for next time, go to saving volume with PlayerData. To tune per-device usability, go to settings panels that work for everyone.

VRChat Notes in this section63