using System; using System.Collections.Generic; using Unity.Netcode; using UnityEngine; namespace Unity.BossRoom.Gameplay.GameplayObjects { /// /// Server-side logic for a floor switch (a/k/a "pressure plate"). /// This script should be attached to a physics trigger. /// [RequireComponent(typeof(Collider))] public class FloorSwitch : NetworkBehaviour { [SerializeField] Animator m_Animator; [SerializeField] Collider m_Collider; public NetworkVariable IsSwitchedOn { get; } = new NetworkVariable(); List m_RelevantCollidersInTrigger = new List(); const string k_AnimatorPressedDownBoolVarName = "IsPressed"; [SerializeField, HideInInspector] int m_AnimatorPressedDownBoolVarID; void Awake() { m_Collider.isTrigger = true; } public override void OnNetworkSpawn() { if (!IsServer) { enabled = false; } FloorSwitchStateChanged(false, IsSwitchedOn.Value); IsSwitchedOn.OnValueChanged += FloorSwitchStateChanged; } void OnTriggerEnter(Collider other) { // no need to check for layer; layer matrix has been configured to only allow FloorSwitch x PC interactions m_RelevantCollidersInTrigger.Add(other); } void OnTriggerExit(Collider other) { m_RelevantCollidersInTrigger.Remove(other); } void FixedUpdate() { // it's possible that the Colliders in our trigger have been destroyed, while still inside our trigger. // In this case, OnTriggerExit() won't get called for them! We can tell if a Collider was destroyed // because its reference will become null. So here we remove any nulls and see if we're still active. m_RelevantCollidersInTrigger.RemoveAll(col => col == null); IsSwitchedOn.Value = m_RelevantCollidersInTrigger.Count > 0; } void FloorSwitchStateChanged(bool previousValue, bool newValue) { m_Animator.SetBool(m_AnimatorPressedDownBoolVarID, newValue); } void OnValidate() { m_AnimatorPressedDownBoolVarID = Animator.StringToHash(k_AnimatorPressedDownBoolVarName); } } }