diff --git a/Assets/Scenes/BossRoom/DungeonEntrance.unity b/Assets/Scenes/BossRoom/DungeonEntrance.unity index 58d2019..6301c23 100644 --- a/Assets/Scenes/BossRoom/DungeonEntrance.unity +++ b/Assets/Scenes/BossRoom/DungeonEntrance.unity @@ -595,6 +595,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: + PlatformID: + m_InternalValue: 0 --- !u!64 &249976107358570839 MeshCollider: m_ObjectHideFlags: 0 @@ -788,6 +790,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: + PlatformID: + m_InternalValue: 0 --- !u!64 &1223475210011116503 MeshCollider: m_ObjectHideFlags: 0 @@ -982,6 +986,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: + PlatformID: + m_InternalValue: 0 --- !u!64 &1326862948614608681 MeshCollider: m_ObjectHideFlags: 0 @@ -1160,6 +1166,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: + PlatformID: + m_InternalValue: 0 --- !u!64 &3169561862507413954 MeshCollider: m_ObjectHideFlags: 0 @@ -1338,6 +1346,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: + PlatformID: + m_InternalValue: 0 --- !u!64 &5215249593494578416 MeshCollider: m_ObjectHideFlags: 0 @@ -1516,6 +1526,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: + PlatformID: + m_InternalValue: 0 --- !u!64 &5615547279758710380 MeshCollider: m_ObjectHideFlags: 0 @@ -1694,6 +1706,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Name: m_EditorClassIdentifier: + PlatformID: + m_InternalValue: 0 --- !u!64 &7017483914677023159 MeshCollider: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacter.cs b/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacter.cs index 9839310..8d704a5 100644 --- a/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacter.cs +++ b/Assets/Scripts/Gameplay/GameplayObjects/Character/ServerCharacter.cs @@ -307,7 +307,7 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character private void HandleOccupiedPlatform(Platform currentPlatform) { - var nearestPlatform = PlatformManager.Instance.FindNearestUnoccupiedPlatform(transform.position); + var nearestPlatform = PlatformManager.Instance.GetNearestAvailablePlatform(transform.position); if (nearestPlatform != null) { Debug.Log($"Platform {currentPlatform.PlatformID} is occupied. Moving to nearest Platform {nearestPlatform.PlatformID}."); @@ -322,14 +322,25 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character private void MoveToPlatform(Platform platform) { - SetTargetPlatform(platform.PlatformID); - var pltpos = PlatformManager.Instance.GetPlatformPosition(platform.PlatformID); - pltpos.y = 0; + int platformID = platform.PlatformID.Value; // Access the value of NetworkVariable + SetTargetPlatform(platformID); // Set the target platform ID + var pltpos = PlatformManager.Instance.GetPlatformPosition(platformID); // Get platform position + pltpos.y = 0; // Reset Y-axis position for movement Debug.Log($"Platform position: {pltpos}."); IsSwapping = true; - ServerSendCharacterInputRpc(pltpos); + ServerSendCharacterInputRpc(pltpos); // Send the movement request } + //private void MoveToPlatform(Platform platform) + //{ + // SetTargetPlatform(platform.PlatformID); + // var pltpos = PlatformManager.Instance.GetPlatformPosition(platform.PlatformID); + // pltpos.y = 0; + // Debug.Log($"Platform position: {pltpos}."); + // IsSwapping = true; + // ServerSendCharacterInputRpc(pltpos); + //} + private void BecomeCrow() { ClearTargetPlatform(); @@ -378,8 +389,8 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character public void InitiateSwap(ServerCharacter initiatingPlayer, ServerCharacter targetPlayer) { - var initiatingPlatform = PlatformManager.Instance.GetPlatformOccupiedByPlayer(initiatingPlayer); - var targetPlatform = PlatformManager.Instance.GetPlatformOccupiedByPlayer(targetPlayer); + var initiatingPlatform = PlatformManager.Instance.GetPlayerPlatform(initiatingPlayer); + var targetPlatform = PlatformManager.Instance.GetPlayerPlatform(targetPlayer); if (initiatingPlatform == null || targetPlatform == null) { diff --git a/Assets/Scripts/Gameplay/Platform.cs b/Assets/Scripts/Gameplay/Platform.cs index 1c7ca06..d05bd4b 100644 --- a/Assets/Scripts/Gameplay/Platform.cs +++ b/Assets/Scripts/Gameplay/Platform.cs @@ -9,184 +9,97 @@ namespace Unity.Multiplayer.Samples.BossRoom [RequireComponent(typeof(Collider))] public class Platform : NetworkBehaviour { - public int PlatformID { get; private set; } + public NetworkVariable PlatformID = new NetworkVariable(0); public bool IsOccupied { get; private set; } - private NetworkVariable OccupierId = new NetworkVariable(0, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); - private Collider m_PlatformCollider; + private NetworkVariable occupierId = new NetworkVariable(0, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); + private Collider platformCollider; private Animator animator; - private NetworkAnimator networkAnimator; - public void PauseAnimation() + private void Awake() + { + platformCollider = GetComponent(); + if (!platformCollider.isTrigger) + platformCollider.isTrigger = true; + + animator = GetComponent(); + } + + public void Initialize(int id) + { + if (IsServer) PlatformID.Value = id; + } + + public void StartRotation() => transform.DOLocalRotate(Vector3.up, 120).SetSpeedBased(true).SetId(PlatformID).SetLoops(-1, LoopType.Incremental); + + private void PauseRotation() => DOTween.Pause(PlatformID); + private void ResumeRotation() => DOTween.Play(PlatformID); + + public void Pause() { if (IsOwner) { - // Pause the animation locally animator.speed = 0f; - - // Inform the server to pause animation for all clients - PauseAnimationServerRpc(); + PauseServerRpc(); } } - public void ResumeAnimation() + public void Resume() { if (IsOwner) { - // Resume the animation locally animator.speed = 1f; - - // Inform the server to resume animation for all clients - ResumeAnimationServerRpc(); + ResumeServerRpc(); } } [ServerRpc] - private void PauseAnimationServerRpc() - { - // On the server, pause animation for all clients - PauseAnimationClientRpc(); - } - + private void PauseServerRpc() => PauseClientRpc(); [ClientRpc] - private void PauseAnimationClientRpc() - { - animator.speed = 0f; - } + private void PauseClientRpc() => animator.speed = 0f; [ServerRpc] - private void ResumeAnimationServerRpc() - { - // On the server, resume animation for all clients - ResumeAnimationClientRpc(); - } - + private void ResumeServerRpc() => ResumeClientRpc(); [ClientRpc] - private void ResumeAnimationClientRpc() - { - animator.speed = 1f; - } - private void Awake() - { - m_PlatformCollider = GetComponent(); - if (!m_PlatformCollider.isTrigger) - { - Debug.LogWarning($"Platform {name} collider must be set as a trigger."); - m_PlatformCollider.isTrigger = true; // Ensure it's a trigger. - } - animator = GetComponent(); - networkAnimator = GetComponent(); - } + private void ResumeClientRpc() => animator.speed = 1f; - public void AssignID(int id) - { - PlatformID = id; - IsOccupied = false; - Debug.Log($"Platform {name} assigned ID: {PlatformID}"); - } - public void AnimationStarter() - { - transform.DOLocalRotate(Vector3.up, 120).SetSpeedBased(true).SetId(PlatformID).SetLoops(-1, LoopType.Incremental); - } - void AnimationResumer() - { - Debug.Log("Play PlatformID: " + PlatformID); - DOTween.Play(PlatformID); - } - void AnimationPauser() - { - Debug.Log("Pause PlatformID: " + PlatformID); - DOTween.Pause(PlatformID); - } public void Occupy(ServerCharacter player) { - if (!IsServer) - { - Debug.LogError("Occupy can only be called on the server."); - return; - } - PauseAnimation(); - if (IsOccupied) - { - Debug.LogWarning($"Platform {PlatformID} is already occupied."); - return; - } - bool giveScore = player.PreviousPlatformId != PlatformID; - // Check if the player who occupied this platform had this platform as their target platform - if (giveScore) - { - if (player.TargetPlatformId.HasValue && player.TargetPlatformId.Value == PlatformID) - { - // Successful swap - ScoreManager.Instance.AddPlayerScore(player.OwnerClientId, 10); - Debug.Log($"Player {player.OwnerClientId} successfully swapped to Platform {PlatformID}. Awarded 10 score."); - } - else - { - ScoreManager.Instance.AddPlayerScore(player.OwnerClientId, 20); - Debug.Log($"Crow Player {player.OwnerClientId} successfully stole Platform {PlatformID}. Awarded 20 score."); - } - } + if (!IsServer || IsOccupied) return; + + Pause(); + bool giveScore = player.PreviousPlatformId != PlatformID.Value; + int score = (player.TargetPlatformId == PlatformID.Value) ? 10 : 20; + + if (giveScore) ScoreManager.Instance.AddPlayerScore(player.OwnerClientId, score); + IsOccupied = true; - OccupierId.Value = player.OwnerClientId; - player.OnArrivalOnPlatform(PlatformID); - Debug.Log($"Platform {PlatformID} is now occupied by Player {player.OwnerClientId}."); + occupierId.Value = player.OwnerClientId; + player.OnArrivalOnPlatform(PlatformID.Value); } - public void Vacate(ServerCharacter player) { - if (!IsServer) - { - Debug.LogError("Vacate can only be called on the server."); - return; - } - ResumeAnimation(); + if (!IsServer || !IsOccupied || occupierId.Value != player.OwnerClientId) return; - if (!IsOccupied || OccupierId.Value != player.OwnerClientId) - { - Debug.LogWarning($"Platform {PlatformID} is not occupied by Player {player.OwnerClientId}."); - return; - } + Resume(); IsOccupied = false; - OccupierId.Value = 0; - player.OnLeavingPlatform(PlatformID); - - Debug.Log($"Platform {PlatformID} is now vacated."); + occupierId.Value = 0; + player.OnLeavingPlatform(PlatformID.Value); } private void OnTriggerEnter(Collider other) { - if (!IsServer) return; - - if (other.TryGetComponent(out var player)) - { - if (!IsOccupied) - { - Occupy(player); - } - else - { - Debug.Log($"Player {player.OwnerClientId} attempted to occupy an already occupied Platform {PlatformID}."); - } - } - } - - public ulong GetOccupierId() - { - return OccupierId.Value; + if (IsServer && other.TryGetComponent(out var player) && !IsOccupied) + Occupy(player); } private void OnTriggerExit(Collider other) { - if (!IsServer) return; - if (other.TryGetComponent(out var player)) - { + if (IsServer && other.TryGetComponent(out var player)) Vacate(player); - if (OccupierId.Value == player.OwnerClientId) - player.OnLeavingPlatform(PlatformID); - - } } + + public ulong GetOccupierId() => occupierId.Value; } } diff --git a/Assets/Scripts/Gameplay/PlatformManager.cs b/Assets/Scripts/Gameplay/PlatformManager.cs index 4713a54..2171339 100644 --- a/Assets/Scripts/Gameplay/PlatformManager.cs +++ b/Assets/Scripts/Gameplay/PlatformManager.cs @@ -1,3 +1,4 @@ +using System.Collections; using System.Collections.Generic; using System.Linq; using Unity.BossRoom.Gameplay.GameplayObjects.Character; @@ -9,112 +10,81 @@ namespace Unity.Multiplayer.Samples.BossRoom public class PlatformManager : NetworkBehaviour { public static PlatformManager Instance; - public List m_Platforms; - public int numberOfPlayers = 2; // Number of players (n) - public float planeRadius = 4f; // Radius of the circular plane + private List platforms; private void Awake() { if (Instance != null && Instance != this) - { Destroy(gameObject); - } else - { Instance = this; - } } private void Start() { - //if (IsServer) // Ensure only the server assigns IDs and initializes - { - m_Platforms = GetComponentsInChildren().ToList(); - - 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."); - Starter(); - } - } - void Starter() - { - int platformsToSpawn = PlayerPrefs.GetInt("NumberOfLobbyPlayers") - 1; - if (platformsToSpawn <= 0) return; - - m_Platforms.ForEach(platform => platform.gameObject.SetActive(false)); - for (int i = 0; i < platformsToSpawn; i++) m_Platforms[i].gameObject.SetActive(true); - m_Platforms = m_Platforms.Where(p => p.gameObject.activeInHierarchy).ToList(); - - float angleIncrement = 360f / platformsToSpawn; - for (int i = 0; i < platformsToSpawn; i++) - m_Platforms[i].transform.position = new Vector3( - Mathf.Cos(i * angleIncrement * Mathf.Deg2Rad) * planeRadius, - 0f, - Mathf.Sin(i * angleIncrement * Mathf.Deg2Rad) * planeRadius - ); + platforms = GetComponentsInChildren(true).ToList(); + if (IsServer) StartCoroutine(ServerSetup()); + else StartCoroutine(ClientSetup()); } - public Platform FindNearestUnoccupiedPlatform(Vector3 position) + private IEnumerator ServerSetup() { - 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)) - .FirstOrDefault(); + yield return new WaitForSeconds(0.5f); + ActivatePlatformsServerRpc(); } - public bool AreAllPlatformsOccupied() + private IEnumerator ClientSetup() { - return m_Platforms.All(platform => platform.IsOccupied); + yield return new WaitForSeconds(0.5f); + platforms = GetComponentsInChildren(true).ToList(); } - public bool AssignPlayerToPlatform(ServerCharacter player) + [ServerRpc(RequireOwnership = false)] + private void ActivatePlatformsServerRpc() { - 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) - { - platform.Occupy(player); - return true; - } - - Debug.LogWarning($"No unoccupied platforms available for {player.name}."); - return false; - } + int activeCount = PlayerPrefs.GetInt("NumberOfLobbyPlayers") - 1; + if (activeCount <= 0) return; - public Platform GetPlatformOccupiedByPlayer(ServerCharacter player) - { - return m_Platforms.FirstOrDefault(p => p.IsOccupied && p.GetOccupierId() == player.OwnerClientId); + platforms.ForEach(p => p.gameObject.SetActive(false)); + for (int i = 0; i < activeCount; i++) + platforms[i].gameObject.SetActive(true); + + var activeIds = platforms.Where(p => p.gameObject.activeSelf).Select(p => p.PlatformID.Value).ToArray(); + ActivatePlatformsClientRpc(activeIds); } - public bool IsPlatformOccupied(Platform platform) + [ClientRpc] + private void ActivatePlatformsClientRpc(int[] platformIds) { - return platform.IsOccupied; + platforms = GetComponentsInChildren(true).ToList(); + platforms.ForEach(p => p.gameObject.SetActive(false)); + + foreach (int id in platformIds) + platforms.FirstOrDefault(p => p.PlatformID.Value == id)?.gameObject.SetActive(true); } - public Vector3 GetPlatformPosition(int platformId) + public Platform GetNearestAvailablePlatform(Vector3 position) { - var platform = m_Platforms.FirstOrDefault(p => p.PlatformID == platformId); - return platform ? platform.transform.position : Vector3.zero; + return IsServer ? platforms.Where(p => !p.IsOccupied).OrderBy(p => Vector3.Distance(position, p.transform.position)).FirstOrDefault() : null; } - public Platform GetPlatformById(int platformId) + public bool AllPlatformsOccupied() => platforms.All(p => p.IsOccupied); + + public bool AssignPlayerToPlatform(ServerCharacter player) { - return m_Platforms.FirstOrDefault(p => p.PlatformID == platformId); + if (!IsServer) return false; + + var availablePlatform = platforms.FirstOrDefault(p => !p.IsOccupied); + if (availablePlatform == null) return false; + + availablePlatform.Occupy(player); + return true; } + + public Platform GetPlayerPlatform(ServerCharacter player) => platforms.FirstOrDefault(p => p.IsOccupied && p.GetOccupierId() == player.OwnerClientId); + + public Vector3 GetPlatformPosition(int platformId) => platforms.FirstOrDefault(p => p.PlatformID.Value == platformId)?.transform.position ?? Vector3.zero; + + public Platform GetPlatformById(int platformId) => platforms.FirstOrDefault(p => p.PlatformID.Value == platformId); } } diff --git a/Assets/Scripts/Gameplay/ScoreManager.cs b/Assets/Scripts/Gameplay/ScoreManager.cs index 488da8e..5076bb7 100644 --- a/Assets/Scripts/Gameplay/ScoreManager.cs +++ b/Assets/Scripts/Gameplay/ScoreManager.cs @@ -101,7 +101,7 @@ public class ScoreManager : NetworkBehaviour private IEnumerator ApplyCrowPenaltyCoroutine() { - yield return new WaitUntil(() => PlatformManager.Instance != null && PlatformManager.Instance.AreAllPlatformsOccupied()); + yield return new WaitUntil(() => PlatformManager.Instance != null && PlatformManager.Instance.AllPlatformsOccupied()); while (true) {