You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
3.3 KiB
C#
116 lines
3.3 KiB
C#
3 weeks ago
|
using System;
|
||
|
using Unity.BossRoom.Gameplay.Messages;
|
||
|
using Unity.BossRoom.Infrastructure;
|
||
|
using Unity.Netcode;
|
||
|
using UnityEngine;
|
||
|
using VContainer;
|
||
|
|
||
|
namespace Unity.BossRoom.Gameplay.GameplayObjects
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// This class contains both client and server logic for a door that is opened when a player stands on a floor switch.
|
||
|
/// (Assign the floor switches for this door in the editor.)
|
||
|
/// Represents a door in the client. The visuals of the door animate as
|
||
|
/// "opening" and "closing", but for physics purposes this is an illusion:
|
||
|
/// whenever the door is open on the server, the door's physics are disabled,
|
||
|
/// and vice versa.
|
||
|
/// </summary>
|
||
|
public class SwitchedDoor : NetworkBehaviour
|
||
|
{
|
||
|
[SerializeField]
|
||
|
FloorSwitch[] m_SwitchesThatOpenThisDoor;
|
||
|
|
||
|
[SerializeField]
|
||
|
Animator m_Animator;
|
||
|
|
||
|
public NetworkVariable<bool> IsOpen { get; } = new NetworkVariable<bool>();
|
||
|
|
||
|
const string k_AnimatorDoorOpenBoolVarName = "IsOpen";
|
||
|
|
||
|
[SerializeField, HideInInspector]
|
||
|
int m_AnimatorDoorOpenBoolID;
|
||
|
|
||
|
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||
|
public bool ForceOpen;
|
||
|
#endif
|
||
|
|
||
|
[SerializeField]
|
||
|
[Tooltip("This physics and navmesh obstacle is enabled when the door is closed.")]
|
||
|
GameObject m_PhysicsObject;
|
||
|
|
||
|
[Inject]
|
||
|
IPublisher<DoorStateChangedEventMessage> m_Publisher;
|
||
|
|
||
|
void Awake()
|
||
|
{
|
||
|
if (m_SwitchesThatOpenThisDoor.Length == 0)
|
||
|
Debug.LogError("Door has no switches and can never be opened!", gameObject);
|
||
|
}
|
||
|
|
||
|
public override void OnNetworkSpawn()
|
||
|
{
|
||
|
IsOpen.OnValueChanged += OnDoorStateChanged;
|
||
|
|
||
|
if (IsClient)
|
||
|
{
|
||
|
// initialize visuals based on current server state (or else we default to "closed")
|
||
|
m_PhysicsObject.SetActive(!IsOpen.Value);
|
||
|
}
|
||
|
|
||
|
if (IsServer)
|
||
|
{
|
||
|
OnDoorStateChanged(false, IsOpen.Value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void OnNetworkDespawn()
|
||
|
{
|
||
|
IsOpen.OnValueChanged -= OnDoorStateChanged;
|
||
|
}
|
||
|
|
||
|
void Update()
|
||
|
{
|
||
|
if (IsServer && IsSpawned)
|
||
|
{
|
||
|
var isAnySwitchOn = false;
|
||
|
foreach (var floorSwitch in m_SwitchesThatOpenThisDoor)
|
||
|
{
|
||
|
if (floorSwitch && floorSwitch.IsSwitchedOn.Value)
|
||
|
{
|
||
|
isAnySwitchOn = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||
|
isAnySwitchOn |= ForceOpen;
|
||
|
#endif
|
||
|
|
||
|
IsOpen.Value = isAnySwitchOn;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OnDoorStateChanged(bool wasDoorOpen, bool isDoorOpen)
|
||
|
{
|
||
|
if (IsServer)
|
||
|
{
|
||
|
m_Animator.SetBool(m_AnimatorDoorOpenBoolID, isDoorOpen);
|
||
|
}
|
||
|
|
||
|
if (IsClient)
|
||
|
{
|
||
|
m_PhysicsObject.SetActive(!isDoorOpen);
|
||
|
if (m_Publisher != null)
|
||
|
{
|
||
|
m_Publisher.Publish(new DoorStateChangedEventMessage() { IsDoorOpen = isDoorOpen });
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OnValidate()
|
||
|
{
|
||
|
m_AnimatorDoorOpenBoolID = Animator.StringToHash(k_AnimatorDoorOpenBoolVarName);
|
||
|
}
|
||
|
}
|
||
|
}
|