// PlayerVisibility.cs // Click this object to turn invisible; click it again (or press the Appear button, G on desktop) to come back. Everybody // else stops seeing your avatar, its name tag and voice meter; you still see yourself (faded, like a ghost) unless See // Yourself is off. You stay invisible when you change outfits, and players who join later do not see you either. // // Set up: put this script on any clickable object (a cube). Optional: Vanish For Seconds (0 = until you come back), // an Everyone Button object that hides / shows every player at once, and the /vanish and /appear chat commands. using System.Collections; using System.Collections.Generic; using IHXR.Simulation; public class PlayerVisibility : ScriptBase { [Tooltip("Whether invisible players still see themselves (faded, like a ghost).")] public bool SeeYourself = true; [Tooltip("Seconds until an invisible player shows again (0 = until they come back themselves).")] [Range(0, 600)] public float VanishForSeconds = 0f; public string ClickHint = "Turn invisible"; [Tooltip("Optional: an object that hides or shows every player at once.")] public SceneObject EveryoneButton; [Tooltip("The /vanish and /appear chat commands.")] public bool ChatCommands = true; private readonly Dictionary timers = new Dictionary(); private bool everyoneHidden; public override void Start() { MakeInteractable(click => Toggle(click.Username), true, null, true, 10f, ClickHint); if (EveryoneButton != null && !EveryoneButton.IsNull) MakeInteractable(EveryoneButton, click => ToggleEveryone(), true, null, true, 10f, "Hide / show everyone"); // While invisible, a player has an Appear button (on screen, G on desktop, right stick click in VR). ListenForActionButton("appear", info => { if (info.State == ActionButtonState.Down) Appear(info.Username); }); if (ChatCommands) { RegisterChatCommand("vanish", command => Vanish(command.Username)); RegisterChatCommand("appear", command => Appear(command.Username)); } } private void Toggle(string user) { if (IsPlayerVisible(user)) Vanish(user); else Appear(user); } private void Vanish(string user) { HidePlayer(user, !SeeYourself); ShowActionButton(user, "appear", "Appear", "G"); StopTimer(user); if (VanishForSeconds > 0f) timers[Key(user)] = StartCoroutine(AppearAfter(user, VanishForSeconds)); } private void Appear(string user) { StopTimer(user); ShowPlayer(user); HideActionButton(user, "appear"); } private void ToggleEveryone() { everyoneHidden = !everyoneHidden; foreach (UserInfo user in GetUsers()) { if (everyoneHidden) Vanish(user.Username); else Appear(user.Username); } } private IEnumerator AppearAfter(string user, float seconds) { yield return new WaitForSeconds(seconds); timers.Remove(Key(user)); Appear(user); } private void StopTimer(string user) { if (timers.TryGetValue(Key(user), out Coroutine timer)) { StopCoroutine(timer); timers.Remove(Key(user)); } } private static string Key(string user) { return (user ?? "").ToLowerInvariant(); } // A player who leaves comes back visible (the server shows them again). public override void OnUserPart(UserInfo user) { if (user != null) StopTimer(user.Username); } }