Build a VRChat World Settings Menu
A world settings menu should make personal controls easy to find without changing the experience for everyone else. This guide covers the current VRChat workflow for a point-and-click world-space Canvas, local options, saved per-player preferences, and the smaller set of controls that genuinely need instance-wide synchronization.
Build the Canvas first, classify each setting by scope, and add persistence or networking only where required.
- Create a VRChat-compatible Canvas with readable labels and a small set of controls.
- Add VRC Ui Shape and verify the pointer can reach every control.
- Keep personal settings local; use PlayerData only when a preference should survive future visits.
- Use synchronized variables only for settings that every player must share.
- Test the menu on desktop, in VR, and on mobile before publishing.
For 2D world UI, VRChat directs creators to use VRC Ui Shape with Unity UI controls. Players can point, click, and scroll the Canvas from a distance, and phone or tablet users can use Focus View when it is enabled.
Video Companion
Fionna's original CyanTrigger tutorial demonstrates an event-and-action approach to world UI. Use the video for its visual walkthrough, then apply the current scope, persistence, and testing rules in this guide.
Video creator: Fionna
Decide Who Owns Each Setting
Classify every option before wiring its UI event.
| Setting scope | Implementation | Example |
|---|---|---|
| Personal for this visit | Local Udon variable or direct local UI action | Mirror visibility, personal volume, comfort effects, local post-processing. |
| Personal across future visits | PlayerData, read after OnPlayerRestored |
Preferred volume, captions, accessibility choices, personal visual effects. |
| Shared persistent state for the current instance | Synced variable with an ownership and serialization plan | Game mode, public room lighting state, shared media controls. |
| Temporary action for current players | Network event when the action truly needs a shared one-time signal | A short animation or sound cue. |
Personal controls should not become network traffic. A player's mirror, volume, or comfort preference normally belongs on that player's client.
Create the World-Space Canvas
VRChat's SDK can configure the required Canvas components when you create UI > TextMeshPro (VRC) from the Unity Hierarchy menu.
Use this setup checklist:
- Place the Canvas where players can approach or point at it comfortably.
- Confirm the Canvas has a
VRC Ui Shapecomponent. - Keep the Canvas and its children off Unity's
UIlayer; VRChat documents the Default layer as a working choice. - Confirm the UI Shape's Box Collider covers the interactive area.
- Use TextMeshPro controls for readable text.
- Set Navigation to None on UI controls so movement inputs do not change menu values.
- Set a scroll area's Scroll Sensitivity to
0when movement input should not scroll it. - Enable Allow Focus View when phone and tablet users should be able to expand, pan, and zoom the menu.
Focus View is provided by VRC Ui Shape for phone and tablet players. Test the menu in both portrait and landscape layouts if the world depends on mobile access.
Design the Menu Structure
Use direct labels and keep related options together:
| Section | Suitable controls |
|---|---|
| Audio | Personal music, ambient, effects, or voice-related world controls. |
| Visuals | Personal mirrors, post-processing, particles, screen effects, or lighting alternatives. |
| Comfort | Motion effects, camera effects, flashing effects, or other optional sensory changes. |
| Accessibility | Captions, text size, contrast, interaction alternatives, and persistent personal preferences. |
| Shared world | Clearly identified controls that intentionally change the instance for everyone. |
Mark shared controls as shared. A player should not discover after clicking that a personal-looking toggle changed the room for everyone.
Wire Buttons, Toggles, and Sliders
VRChat allows Unity UI events to call a defined list of component methods directly. For example, UI events can control supported properties and methods on components such as Animator and AudioSource.
Use one of these patterns:
Direct allowed UI action
Use the control's Unity event when the target method or property is on VRChat's allowed UI event list and no extra logic is required.
Udon custom event
Use an UdonBehaviour when the control needs validation, multiple actions, persistence, synchronization, or state-dependent logic.
- Enter the custom event name exactly the same way in the UI event and UdonBehaviour.
- For UdonSharp, the target method must be public when called with
SendCustomEvent. - Keep local settings on local methods; do not turn a local button into a network event.
- Apply the setting through one reusable method so initialization and UI changes produce the same result.
Value control
For a Toggle or Slider:
- Read the current UI value.
- Store it in the correct local, persistent, or synchronized variable.
- Apply the result to the target components.
- Update labels or value readouts.
- Save or serialize only when that setting's scope requires it.
Build Local Personal Settings
A local setting only needs:
- the current value
- the UI control
- the target component or behaviour
- one method that applies the value
For example, a personal mirror toggle can enable or disable the mirror object locally. A personal volume slider can change a local AudioSource volume without informing other players.
Initialize the control and target from the same stored value. This prevents the visible UI state from disagreeing with the world effect.
Save Preferences with PlayerData
PlayerData is VRChat's key-value storage for data associated with a player in one world. VRChat lists world preferences as a suitable use.
Use this sequence:
- Wait for
OnPlayerRestoredfor the local player. - Attempt to read the specific preference key.
- If the key exists, copy its value into the local settings model.
- If it does not exist, keep the documented default.
- Apply the value to the world effect and its UI control.
- When the player changes the option, update the local effect and write the new PlayerData value.
Do not read or write PlayerData before OnPlayerRestored. VRChat warns that early values may be overwritten when saved data finishes loading.
Use distinct, prefixed keys such as:
VRCreators-Settings-MusicVolume
VRCreators-Settings-Captions
VRCreators-Settings-ComfortEffects
VRChat recommends prefixes for prefab PlayerData keys to reduce collisions with other systems.
Build Shared Instance Settings
Only add networking when every player must observe the same state.
For a shared toggle:
- Store the state in a synced variable.
- Ensure the player changing it can write the variable by checking or transferring ownership.
- Change the value as the owner.
- Call
RequestSerialization()when the behaviour uses manual synchronization. - Apply the received value when synchronization updates.
- Update the menu without treating the programmatic UI refresh as a new player request.
Use a synced variable, not only a network event, when late joiners must receive the current setting.
Keep UI State and World State Together
Use one application path for each setting:
Control input
→ validate and store value
→ apply value to world objects
→ update visible control state
→ persist or synchronize when required
The same application path should run after PlayerData restoration and synchronized-variable updates. This avoids separate startup, click, and networking implementations drifting apart.
Cross-Platform UI Checklist
- Use large, direct labels that remain readable at the intended viewing distance.
- Give buttons, toggles, and sliders enough spacing for pointing.
- Do not rely on colour alone to communicate enabled and disabled states.
- Provide a visible value for important sliders.
- Keep critical options out of deep scrolling areas.
- Check that the Canvas Collider covers the entire interactive surface.
- Set Navigation to None on all controls.
- Test Focus View when mobile support is intended.
- Confirm shared controls are labelled as shared.
- Provide a reset-to-default action for personal settings when practical.
Test the Settings Menu
| Test | What to verify |
|---|---|
| Unity Play Mode | Controls call the expected allowed method or Udon event. |
| ClientSim | Pointer interaction, values, labels, local effects, and PlayerData restoration behave correctly. |
| Desktop VRChat | Mouse interaction works and movement input does not alter UI values. |
| VR controller | Controls are reachable, readable, and usable from the intended distance. |
| Phone or tablet | Focus View, scrolling, orientation, and touch interaction remain usable. |
| Second client | Personal settings remain personal and shared settings update correctly. |
| Late join | Shared synchronized settings appear in their current state. |
| Return visit | PlayerData preferences restore only after OnPlayerRestored. |
ClientSim can simulate PlayerData and provides a PlayerData editor for inspecting stored keys and values. Finish with an uploaded private test because ClientSim cannot reproduce every part of the VRChat client or remote-player networking.
Release Checklist
- [ ] Every setting is classified as local, persistent personal, shared state, or temporary shared action.
- [ ] The Canvas uses VRC Ui Shape and a correctly sized Collider.
- [ ] Canvas objects are not on Unity's UI layer.
- [ ] Navigation is None on every control.
- [ ] Custom event names match exactly.
- [ ] UdonSharp methods called by UI events are public.
- [ ] PlayerData reads wait for
OnPlayerRestored. - [ ] Persistent keys use a unique prefix.
- [ ] Shared synced values have an ownership and serialization path.
- [ ] Late joiners receive current shared state.
- [ ] Desktop, VR, mobile, return-visit, and multiplayer tests pass.
Troubleshooting
The VRChat pointer does not appear over the Canvas.
Confirm VRC Ui Shape is on the Canvas, the Canvas is not on Unity's UI layer, and the Box Collider covers the interactive area. Also verify the Canvas faces the player from the intended side.
The button responds visually but its action never runs.
Check that the selected Unity UI target is on VRChat's allowed list. For SendCustomEvent, match the event name exactly and make the target UdonSharp method public.
Walking or moving a joystick changes the controls.
Set Navigation to None on every UI control. For scroll areas that should ignore movement input, set Scroll Sensitivity to 0.
Saved preferences reset or load the wrong default.
Wait for OnPlayerRestored before reading or writing PlayerData. Check the exact key and value type, then apply the restored value to both the control and the target effect.
A personal setting changes the world for everyone.
Remove the network event or synchronized variable from that option and apply it locally. Reserve networking for controls that are intentionally shared.
Shared settings work for current players but not late joiners.
Store the current setting in a synced variable rather than relying only on a network event. Apply that synchronized value when it is received.
The menu is difficult to use on a phone.
Enable Allow Focus View on VRC Ui Shape, enlarge and separate controls, reduce deep scrolling, and test the menu in portrait and landscape orientations.
Official References
- VRC Ui Shape
- Allowed UI Events
- Udon Event Nodes
- Udon Overview
- PlayerData
- Persistence
- Persistence Examples
- Network Variables
- Object Ownership
- ClientSim PlayerData Editor