using UdonSharp; using UnityEngine; using VRC.SDK3.UdonNetworkCalling; using VRC.SDKBase; using VRC.Udon; using VRC.Udon.Common.Interfaces; public class TeamMachineSwitch : UdonSharpBehaviour { [SerializeField] private Animator switchAnimator; [SerializeField] private AudioSource switchAudioSource; [SerializeField] private Light machineLight; [SerializeField] private PlayerManager playerManager; [SerializeField] private TeamMachineCollider teamMachineCollider; [SerializeField] private AudioSource teamMachineAudioSource; [UdonSynced] private bool isActive = false; private int pendingPlayerId; private string pendingTeam; public override void Interact() { if (!Networking.IsOwner(gameObject)) return; if (!isActive) { // Activate Switch isActive = true; RequestSerialization(); SendCustomNetworkEvent(NetworkEventTarget.All, nameof(OnSwitchActivated)); VRCPlayerApi[] playersInside = teamMachineCollider.GetPlayersInside(); if (playersInside == null || playersInside.Length != 1 || !Utilities.IsValid(playersInside[0])) { SendCustomNetworkEvent(NetworkEventTarget.All, nameof(SetLightYellow)); } else { // Get viable team string availableTeam = playerManager.GetRandomViableTeam(); pendingTeam = availableTeam; pendingPlayerId = playersInside[0].playerId; // Wait 3 seconds then assign SendCustomNetworkEvent(NetworkEventTarget.All, nameof(PlayTeamMachineSound)); SendCustomEventDelayedSeconds(nameof(AssignTeamAndSetColor), 2.6f); } } else { // Deactivate Switch isActive = false; RequestSerialization(); SendCustomNetworkEvent(NetworkEventTarget.All, nameof(OnSwitchDeactivated)); SendCustomNetworkEvent(NetworkEventTarget.All, nameof(SetLightWhite)); } } public void AssignTeamAndSetColor() { // Ensure we are still owner and switch is still active if (!isActive) return; if (!Networking.IsOwner(gameObject)) return; // Assign Team if (playerManager != null) { // Take ownership of PlayerManager to set team if (!Networking.IsOwner(playerManager.gameObject)) { Networking.SetOwner(Networking.LocalPlayer, playerManager.gameObject); } playerManager.SetTeam(pendingPlayerId, pendingTeam); } // Set Light Color if (pendingTeam == "red") SendCustomNetworkEvent(NetworkEventTarget.All, nameof(SetLightRed)); else if (pendingTeam == "blue") SendCustomNetworkEvent(NetworkEventTarget.All, nameof(SetLightBlue)); else SendCustomNetworkEvent(NetworkEventTarget.All, nameof(SetLightWhite)); } [NetworkCallable] public void OnSwitchActivated() { switchAnimator.SetBool("isActive", true); switchAudioSource.Play(); } [NetworkCallable] public void OnSwitchDeactivated() { switchAnimator.SetBool("isActive", false); teamMachineAudioSource.Stop(); switchAudioSource.Play(); } [NetworkCallable] public void SetLightRed() { machineLight.color = Color.red; } [NetworkCallable] public void SetLightBlue() { machineLight.color = Color.blue; } [NetworkCallable] public void SetLightWhite() { machineLight.color = Color.white; } [NetworkCallable] public void SetLightYellow() { machineLight.color = Color.yellow; } [NetworkCallable] public void PlayTeamMachineSound() { teamMachineAudioSource.Play(); } public override void OnDeserialization() { switchAnimator.SetBool("isActive", isActive); } }