From 1afc48072e035f8c027dcaea06096f077ea556e9 Mon Sep 17 00:00:00 2001 From: Hazim Bin Ijaz Date: Mon, 16 Dec 2024 16:38:37 +0500 Subject: [PATCH] Made the stuff networked --- Assets/Scenes/BossRoom.unity | 38 +++- Assets/Scenes/BossRoom/DungeonEntrance.unity | 176 ++++++++++++++++++ Assets/Scripts/Gameplay/CrowManager.cs | 112 +++++++++-- .../Character/ServerCharacter.cs | 31 +-- Assets/Scripts/Gameplay/Platform.cs | 81 +++++--- Assets/Scripts/Gameplay/PlatformManager.cs | 62 +++--- 6 files changed, 392 insertions(+), 108 deletions(-) diff --git a/Assets/Scenes/BossRoom.unity b/Assets/Scenes/BossRoom.unity index 20ec6df..adb106d 100644 --- a/Assets/Scenes/BossRoom.unity +++ b/Assets/Scenes/BossRoom.unity @@ -1084,6 +1084,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 396364068} + - component: {fileID: 396364069} - component: {fileID: 396364067} m_Layer: 0 m_Name: CrowManager @@ -1119,6 +1120,27 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &396364069 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 396364066} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 2177239848 + InScenePlacedSourceGlobalObjectIdHash: 0 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 1 + SpawnWithObservers: 1 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &451210155 GameObject: m_ObjectHideFlags: 0 @@ -8575,11 +8597,11 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 1676734515771252668, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalRotation.w - value: 0.8529446 + value: 0.85294455 objectReference: {fileID: 0} - target: {fileID: 1676734515771252668, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalRotation.x - value: 0.39434478 + value: 0.3943448 objectReference: {fileID: 0} - target: {fileID: 1676734515771252668, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalRotation.y @@ -8587,7 +8609,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 1676734515771252668, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalRotation.z - value: -0.14352977 + value: -0.14352979 objectReference: {fileID: 0} - target: {fileID: 1676734516302391364, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_UpdateMethod @@ -8619,11 +8641,11 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 1676734516695783279, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalRotation.y - value: 0.3097298 + value: 0.30972984 objectReference: {fileID: 0} - target: {fileID: 1676734516695783279, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalRotation.z - value: -0.14506969 + value: -0.1450697 objectReference: {fileID: 0} - target: {fileID: 1676734516724634599, guid: 0193228de87741d40a42e561901c9083, type: 3} propertyPath: m_LocalPosition.z @@ -8736,15 +8758,15 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 203267159508449512, guid: 36b3ee75677a1544191c0ddaaadd8140, type: 3} propertyPath: m_LocalRotation.x - value: 0.3943448 + value: 0.39434484 objectReference: {fileID: 0} - target: {fileID: 203267159508449512, guid: 36b3ee75677a1544191c0ddaaadd8140, type: 3} propertyPath: m_LocalRotation.y - value: 0.31044644 + value: 0.3104465 objectReference: {fileID: 0} - target: {fileID: 203267159508449512, guid: 36b3ee75677a1544191c0ddaaadd8140, type: 3} propertyPath: m_LocalRotation.z - value: -0.14352976 + value: -0.1435298 objectReference: {fileID: 0} - target: {fileID: 203267159508449512, guid: 36b3ee75677a1544191c0ddaaadd8140, type: 3} propertyPath: m_LocalEulerAnglesHint.x diff --git a/Assets/Scenes/BossRoom/DungeonEntrance.unity b/Assets/Scenes/BossRoom/DungeonEntrance.unity index 6a5291d..db9a4ab 100644 --- a/Assets/Scenes/BossRoom/DungeonEntrance.unity +++ b/Assets/Scenes/BossRoom/DungeonEntrance.unity @@ -137,6 +137,7 @@ GameObject: - component: {fileID: 240007730} - component: {fileID: 240007734} - component: {fileID: 240007733} + - component: {fileID: 240007735} m_Layer: 12 m_Name: P (6) m_TagString: Untagged @@ -263,6 +264,27 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!114 &240007735 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 240007728} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 2651067327 + InScenePlacedSourceGlobalObjectIdHash: 0 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 1 + SpawnWithObservers: 1 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &286165426 GameObject: m_ObjectHideFlags: 0 @@ -273,6 +295,7 @@ GameObject: m_Component: - component: {fileID: 286165427} - component: {fileID: 286165428} + - component: {fileID: 286165429} m_Layer: 0 m_Name: Platforms m_TagString: Untagged @@ -314,6 +337,27 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d9e826abe81bf7a4b88597fe93add614, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!114 &286165429 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 286165426} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 635359751 + InScenePlacedSourceGlobalObjectIdHash: 0 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 1 + SpawnWithObservers: 1 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &676920371 GameObject: m_ObjectHideFlags: 0 @@ -328,6 +372,7 @@ GameObject: - component: {fileID: 676920373} - component: {fileID: 676920377} - component: {fileID: 676920376} + - component: {fileID: 676920378} m_Layer: 12 m_Name: P (2) m_TagString: Untagged @@ -454,6 +499,27 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!114 &676920378 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 676920371} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 2844845740 + InScenePlacedSourceGlobalObjectIdHash: 0 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 1 + SpawnWithObservers: 1 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &849256358 GameObject: m_ObjectHideFlags: 0 @@ -468,6 +534,7 @@ GameObject: - component: {fileID: 849256360} - component: {fileID: 849256364} - component: {fileID: 849256363} + - component: {fileID: 849256365} m_Layer: 12 m_Name: P (4) m_TagString: Untagged @@ -594,6 +661,27 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!114 &849256365 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 849256358} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 2133187149 + InScenePlacedSourceGlobalObjectIdHash: 0 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 1 + SpawnWithObservers: 1 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &949745746 GameObject: m_ObjectHideFlags: 0 @@ -726,6 +814,7 @@ GameObject: - component: {fileID: 997499841} - component: {fileID: 997499845} - component: {fileID: 997499844} + - component: {fileID: 997499846} m_Layer: 12 m_Name: P (7) m_TagString: Untagged @@ -852,6 +941,27 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!114 &997499846 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 997499839} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 2541096383 + InScenePlacedSourceGlobalObjectIdHash: 0 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 1 + SpawnWithObservers: 1 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &1146060681 GameObject: m_ObjectHideFlags: 0 @@ -866,6 +976,7 @@ GameObject: - component: {fileID: 1146060683} - component: {fileID: 1146060687} - component: {fileID: 1146060686} + - component: {fileID: 1146060688} m_Layer: 12 m_Name: P (1) m_TagString: Untagged @@ -992,6 +1103,27 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!114 &1146060688 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1146060681} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 4024356049 + InScenePlacedSourceGlobalObjectIdHash: 0 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 1 + SpawnWithObservers: 1 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &1415641637 GameObject: m_ObjectHideFlags: 0 @@ -1112,6 +1244,7 @@ GameObject: - component: {fileID: 1463337824} - component: {fileID: 1463337828} - component: {fileID: 1463337827} + - component: {fileID: 1463337829} m_Layer: 12 m_Name: P (3) m_TagString: Untagged @@ -1238,6 +1371,27 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!114 &1463337829 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1463337822} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 3652105053 + InScenePlacedSourceGlobalObjectIdHash: 0 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 1 + SpawnWithObservers: 1 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &1620155724 GameObject: m_ObjectHideFlags: 0 @@ -1252,6 +1406,7 @@ GameObject: - component: {fileID: 1620155726} - component: {fileID: 1620155730} - component: {fileID: 1620155729} + - component: {fileID: 1620155731} m_Layer: 12 m_Name: P (5) m_TagString: Untagged @@ -1378,6 +1533,27 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!114 &1620155731 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1620155724} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 3970869814 + InScenePlacedSourceGlobalObjectIdHash: 0 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 1 + SpawnWithObservers: 1 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 --- !u!1 &2085312385 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Gameplay/CrowManager.cs b/Assets/Scripts/Gameplay/CrowManager.cs index 5855b89..6ea60dd 100644 --- a/Assets/Scripts/Gameplay/CrowManager.cs +++ b/Assets/Scripts/Gameplay/CrowManager.cs @@ -2,8 +2,9 @@ using System.Collections.Generic; using System.Linq; using Unity.BossRoom.Gameplay.GameplayObjects.Character; using UnityEngine; +using Unity.Netcode; -public class CrowManager : MonoBehaviour +public class CrowManager : NetworkBehaviour { public static CrowManager Instance { get; private set; } @@ -21,17 +22,34 @@ public class CrowManager : MonoBehaviour Instance = this; } - private void Start() + public override void OnNetworkSpawn() { - // players = FindObjectsOfType().ToList(); + if (!IsServer) + { + enabled = false; // Disable CrowManager on clients + return; + } } - private void Update() { + if (!IsServer) return; // Ensure logic only runs on the server DetermineCrow(); } + /// + /// Populates the players list from active ServerCharacters in the scene. + /// + private void PopulatePlayersList() + { + players.Clear(); + players = FindObjectsOfType().ToList(); + Debug.Log("CrowManager: Players list populated."); + } + + /// + /// Determines which player should be the crow. + /// private void DetermineCrow() { int unoccupiedPlayers = 0; @@ -46,33 +64,40 @@ public class CrowManager : MonoBehaviour } } - // If exactly one player is not on a platform, assign as crow if (unoccupiedPlayers == 1) { AssignCrow(potentialCrow); } else if (unoccupiedPlayers == 0 && currentCrow != null) { - // All players are on platforms, clear crow ClearCrow(); } } + /// + /// Assigns a player as the Crow. + /// + /// The ServerCharacter to assign as Crow. private void AssignCrow(ServerCharacter player) { - if (currentCrow == player) return; // Already the crow + if (currentCrow == player) return; if (currentCrow != null) { - // Clear old crow - currentCrow.SetAsCrow(false); + currentCrow.SetAsCrow(false); // Clear old crow } currentCrow = player; currentCrow.SetAsCrow(true); Debug.Log($"{currentCrow.name} is now the Crow."); + + // Notify all clients about the new crow + NotifyCrowChangeClientRpc(currentCrow.OwnerClientId); } + /// + /// Clears the current Crow if no player is unoccupied. + /// private void ClearCrow() { if (currentCrow != null) @@ -80,17 +105,80 @@ public class CrowManager : MonoBehaviour currentCrow.SetAsCrow(false); Debug.Log($"{currentCrow.name} is no longer the Crow."); currentCrow = null; + + // Notify all clients about the crow being cleared + NotifyCrowChangeClientRpc(0); // 0 indicates no crow + } + } + + /// + /// RPC to notify clients about the Crow change. + /// + /// The Client ID of the new crow, or 0 if no crow. + [Rpc(SendTo.Everyone)] + private void NotifyCrowChangeClientRpc(ulong crowClientId) + { + foreach (var player in players) + { + if (player.OwnerClientId == crowClientId) + { + player.SetAsCrow(true); + currentCrow = player; + Debug.Log($"Client: {player.name} is the new Crow."); + } + else + { + player.SetAsCrow(false); + } } } + /// + /// Adds a character to the players list. + /// + /// The ServerCharacter to add. public void AddCharacterToList(ServerCharacter character) { - players.Add(character); + if (!players.Contains(character)) + { + players.Add(character); + Debug.Log($"Player {character.name} added to CrowManager."); + } } + /// + /// Removes a character from the players list. + /// + /// The ServerCharacter to remove. public void RemoveCharacterFromList(ServerCharacter character) { - players.Remove(character); + if (players.Contains(character)) + { + players.Remove(character); + Debug.Log($"Player {character.name} removed from CrowManager."); + } + } + + /// + /// Ensures the players list is updated when a player is spawned or despawned. + /// + /// The ServerCharacter to track. + public void OnPlayerSpawned(ServerCharacter character) + { + AddCharacterToList(character); + } + + public void OnPlayerDespawned(ServerCharacter character) + { + RemoveCharacterFromList(character); + } + + /// + /// Retrieves the current Crow. + /// + /// The current Crow player. + public ServerCharacter GetCurrentCrow() + { + return currentCrow; } - } diff --git a/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacter.cs b/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacter.cs index fb85def..21096ba 100644 --- a/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacter.cs +++ b/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacter.cs @@ -155,6 +155,9 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character NetHealthState = GetComponent(); m_State = GetComponent(); } + + //Hazim + [Rpc(SendTo.Everyone)] private void ShowSwapConfirmationPanelClientRpc() { @@ -172,9 +175,6 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character } } } - - //Hazim - public void SetAsCrow(bool status) { IsCrow = status; @@ -206,27 +206,6 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character IsOnAPlatform = status; } - // private void OnTriggerEnter(Collider other) - // { - // if (TargetPlatformId == null) return; - // - // if (other.TryGetComponent(out Platform platform) && platform.PlatformID == TargetPlatformId) - // { - // if (platform.IsOccupied && platform.Occupier != this) - // { - // Debug.Log($"Platform {platform.PlatformID} was occupied. Now looking for others"); - // // Platform is occupied, handle intervention - // // HandleOccupiedPlatform(platform); - // } - // else - // { - // // Occupy the platform - // Debug.Log($"Platform {platform.PlatformID} is being occupied"); - // platform.Occupy(this); - // ClearTargetPlatform(); - // } - // } - // } private void HandleOccupiedPlatform(Platform currentPlatform) { @@ -319,10 +298,10 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character public override void OnNetworkSpawn() { + CrowManager.Instance.OnPlayerSpawned(this); if (!IsServer) { enabled = false; } else { - CrowManager.Instance.AddCharacterToList(this); NetLifeState.LifeState.OnValueChanged += OnLifeStateChanged; m_DamageReceiver.DamageReceived += ReceiveHP; m_DamageReceiver.CollisionEntered += CollisionEntered; @@ -343,8 +322,8 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character public override void OnNetworkDespawn() { + CrowManager.Instance.OnPlayerDespawned(this); NetLifeState.LifeState.OnValueChanged -= OnLifeStateChanged; - CrowManager.Instance.RemoveCharacterFromList(this); if (m_DamageReceiver) { m_DamageReceiver.DamageReceived -= ReceiveHP; diff --git a/Assets/Scripts/Gameplay/Platform.cs b/Assets/Scripts/Gameplay/Platform.cs index 003a3c7..3596dab 100644 --- a/Assets/Scripts/Gameplay/Platform.cs +++ b/Assets/Scripts/Gameplay/Platform.cs @@ -1,16 +1,16 @@ using Unity.BossRoom.Gameplay.GameplayObjects.Character; +using Unity.Netcode; using UnityEngine; namespace Unity.Multiplayer.Samples.BossRoom { [RequireComponent(typeof(Collider))] - public class Platform : MonoBehaviour + public class Platform : NetworkBehaviour { - public int PlatformID { get; private set; } - public bool IsOccupied => Occupier != null; - public ServerCharacter Occupier { get; private set; } + public bool IsOccupied => OccupierId.Value != 0; + private NetworkVariable OccupierId = new NetworkVariable(0, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); private Collider m_PlatformCollider; private void Awake() @@ -23,64 +23,83 @@ namespace Unity.Multiplayer.Samples.BossRoom } } - /// - /// Sets the unique ID for the platform. - /// - /// The unique ID to assign. public void AssignID(int id) { PlatformID = id; Debug.Log($"Platform {name} assigned ID: {PlatformID}"); } - - /// - /// Marks this platform as occupied by a specific player. - /// - /// The ServerCharacter occupying the platform. + public void Occupy(ServerCharacter player) { + if (!IsServer) + { + Debug.LogError("Occupy can only be called on the server."); + return; + } + if (IsOccupied) { - Debug.LogWarning($"Platform {name} is already occupied by {Occupier.name}."); + Debug.LogWarning($"Platform {PlatformID} is already occupied."); return; } - Occupier = player; - Debug.Log($"{player.name} has occupied Platform {name}."); + OccupierId.Value = player.OwnerClientId; + player.SetOnPlatform(true); + + Debug.Log($"Platform {PlatformID} is now occupied by Player {player.OwnerClientId}."); } - /// - /// Clears the occupation of this platform. - /// - public void Vacate() + public void Vacate(ServerCharacter player) { - if (!IsOccupied) + if (!IsServer) + { + Debug.LogError("Vacate can only be called on the server."); + return; + } + + if (!IsOccupied || OccupierId.Value != player.OwnerClientId) { - Debug.LogWarning($"Platform {name} is not currently occupied."); + Debug.LogWarning($"Platform {PlatformID} is not occupied by Player {player.OwnerClientId}."); return; } - Debug.Log($"{Occupier.name} has vacated Platform {name}."); - Occupier = null; + OccupierId.Value = 0; + player.SetOnPlatform(false); + + Debug.Log($"Platform {PlatformID} is now vacated."); } private void OnTriggerEnter(Collider other) { - if (!IsOccupied && other.TryGetComponent(out var player)) + if (!IsServer) return; + + if (other.TryGetComponent(out var player)) { - Occupy(player); - player.OnArrivalOnPlatform(); - // Debug.Log($"{player.name} has entered Platform {name}."); + if (!IsOccupied) + { + Occupy(player); + player.OnArrivalOnPlatform(); + } + else + { + Debug.Log($"Player {player.OwnerClientId} attempted to occupy an already occupied Platform {PlatformID}."); + } } } + public ulong GetOccupierId() + { + return OccupierId.Value; + } + private void OnTriggerExit(Collider other) { - if (IsOccupied && other.TryGetComponent(out var player) && player == Occupier) + if (!IsServer) return; + + if (other.TryGetComponent(out var player) && OccupierId.Value == player.OwnerClientId) { - Vacate(); + Vacate(player); player.OnLeavingPlatform(); - Debug.Log($"{player.name} has exited Platform {name}."); } } } diff --git a/Assets/Scripts/Gameplay/PlatformManager.cs b/Assets/Scripts/Gameplay/PlatformManager.cs index 6245231..7706d25 100644 --- a/Assets/Scripts/Gameplay/PlatformManager.cs +++ b/Assets/Scripts/Gameplay/PlatformManager.cs @@ -1,14 +1,14 @@ -using System; using System.Collections.Generic; using System.Linq; using Unity.BossRoom.Gameplay.GameplayObjects.Character; +using Unity.Netcode; using UnityEngine; namespace Unity.Multiplayer.Samples.BossRoom { - public class PlatformManager : MonoBehaviour + public class PlatformManager : NetworkBehaviour { - public static PlatformManager Instance = null; + public static PlatformManager Instance; private List m_Platforms; private void Awake() @@ -16,25 +16,37 @@ namespace Unity.Multiplayer.Samples.BossRoom if (Instance != null && Instance != this) { Destroy(gameObject); - } else { + } + else + { Instance = this; } } private void Start() { - m_Platforms = GetComponentsInChildren().ToList(); - // Assign unique IDs to each platform - for (int i = 0; i < m_Platforms.Count; i++) + if (IsServer) // Ensure only the server assigns IDs and initializes { - m_Platforms[i].AssignID(i + 1); // IDs start from 1 - } + m_Platforms = GetComponentsInChildren().ToList(); + + // Assign unique IDs to each platform + for (int i = 0; i < m_Platforms.Count; i++) + { + m_Platforms[i].AssignID(i + 1); // IDs start from 1 + } - Debug.Log("All platforms have been assigned unique IDs."); + Debug.Log("All platforms have been assigned unique IDs."); + } } public Platform FindNearestUnoccupiedPlatform(Vector3 position) { + if (!IsServer) + { + Debug.LogError("FindNearestUnoccupiedPlatform should only be called on the server."); + return null; + } + return m_Platforms .Where(platform => !platform.IsOccupied) .OrderBy(platform => Vector3.Distance(position, platform.transform.position)) @@ -45,15 +57,15 @@ namespace Unity.Multiplayer.Samples.BossRoom { return m_Platforms.All(platform => platform.IsOccupied); } - - - /// - /// Finds an unoccupied platform and assigns the player to it. - /// - /// The ServerCharacter to assign. - /// True if successfully assigned, false otherwise. + public bool AssignPlayerToPlatform(ServerCharacter player) { + if (!IsServer) + { + Debug.LogError("AssignPlayerToPlatform should only be called on the server."); + return false; + } + var platform = m_Platforms.FirstOrDefault(p => !p.IsOccupied); if (platform != null) { @@ -65,26 +77,16 @@ namespace Unity.Multiplayer.Samples.BossRoom return false; } - /// - /// Finds the platform currently occupied by the given player. - /// - /// The ServerCharacter to search for. - /// The platform occupied by the player, or null if not found. public Platform GetPlatformOccupiedByPlayer(ServerCharacter player) { - return m_Platforms.FirstOrDefault(p => p.Occupier == player); + return m_Platforms.FirstOrDefault(p => p.IsOccupied && p.GetOccupierId() == player.OwnerClientId); } - /// - /// Checks if a specific platform is occupied. - /// - /// The platform to check. - /// True if the platform is occupied, false otherwise. public bool IsPlatformOccupied(Platform platform) { return platform.IsOccupied; } - + public Vector3 GetPlatformPosition(int platformId) { var platform = m_Platforms.FirstOrDefault(p => p.PlatformID == platformId); @@ -95,7 +97,5 @@ namespace Unity.Multiplayer.Samples.BossRoom { return m_Platforms.FirstOrDefault(p => p.PlatformID == platformId); } - - } }