forked from tmokmss/com.unity.multiplayer.samples.coop
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SwitchedDoor.cs
112 lines (93 loc) · 3.27 KB
/
SwitchedDoor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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);
m_Publisher?.Publish(new DoorStateChangedEventMessage() { IsDoorOpen = isDoorOpen });
}
}
void OnValidate()
{
m_AnimatorDoorOpenBoolID = Animator.StringToHash(k_AnimatorDoorOpenBoolVarName);
}
}
}