World Utilities / Guides
Owner-controlled features
Let the instance owner switch a feature off for everyone while each player can still opt out.
Some features need two switches: the instance owner decides whether a feature is available at all (say, a loud particle show), and each player decides whether they personally want it. The feature should run only when both agree.
[ Synchronized Boolean ] "show allowed" (owner panel) ─┐
├─▶ [ Boolean Operation: AND ] ─▶ [ Local Boolean ] "show on"
[ Persisted Boolean ] "show wanted" (settings) ──┘ │
▼
[ Object Toggle ] Particle Show
Steps
Following the best practices, each value goes into the group matching its kind.
- Global switch - add a
Synchronized BooleannamedShow AllowedtoGlobal Settings, defaulttrue. Put a Toggle Button for it on an owner-only panel (see below). - Personal switch - add a
Persisted BooleannamedShow WantedtoPersisted Settingswith keysettings.show_wanted, defaulttrue, and a Toggle Button in the regular settings menu. - Result - add a
Local BooleannamedShow OntoLocal Settings/Derived. Its default does not matter; the converter overwrites it. - Combine - add a Boolean Operation converter:
- Target: Type
LOCAL, TargetShow On, OperationAND - A: Type
SYNCHRONIZED, ComponentShow Allowed - B: Type
LOCAL, ComponentShow Wanted
- Target: Type
- Apply - add an Object Toggle with source
Show Onand the particle system as target.
Why a local result? The converter runs on every client. Writing into a synchronized value would make every player take ownership of it in turn - a local result costs nothing and is always correct.
Restricting the owner panel
Anyone can write to a synchronized value, so the owner switch is only as protected as the UI that changes it. World Utilities doesn’t decide who counts as “owner” for you - instance owner, world author, a moderator list - but a tiny script can show the panel to the right people:
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
public class OwnerOnly : UdonSharpBehaviour {
public GameObject panel;
private void Start() { this._Refresh(); }
public override void OnPlayerLeft(VRCPlayerApi player) {
// mastership moves to another player when the master leaves - re-check once it has settled
this.SendCustomEventDelayedSeconds(nameof(this._Refresh), 1f);
}
public void _Refresh() {
// the instance master is usually the person who created the instance
this.panel.SetActive(Networking.IsMaster);
}
}
Networking.IsMasterfollows the instance master, which changes when that player leaves. If you need the actual instance creator, checkNetworking.IsInstanceOwnerinstead.