using System.Collections; 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 : NetworkBehaviour { public static PlatformManager Instance { get; private set; } public List m_Platforms; public Transform centerPoint; public float shapeRadius = 5f; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; } } private void Start() { if (IsServer) { InitializePlatforms(); StartCoroutine(DelayedServerSetup()); } } private void InitializePlatforms() { m_Platforms = GetComponentsInChildren(true).ToList(); for (int i = 0; i < m_Platforms.Count; i++) { m_Platforms[i].AssignID(i + 1); } } private IEnumerator DelayedServerSetup() { yield return new WaitForSeconds(0.5f); PlatformSelection(); } private void PlatformSelection() { int platformsToSpawn = PlayerPrefs.GetInt("NumberOfLobbyPlayers", 1) - 1; // Disable all platforms initially foreach (var platform in m_Platforms) { platform.gameObject.SetActive(false); } // Enable required platforms for (int i = 0; i < platformsToSpawn; i++) { m_Platforms[i].gameObject.SetActive(true); } // Filter only active platforms m_Platforms = m_Platforms.Where(platform => platform.gameObject.activeSelf).ToList(); int[] platformIDs = m_Platforms.Select(p => p.PlatformID.Value).ToArray(); // Arrange the active platforms List arrangedPositions = ArrangePlatforms(m_Platforms); // Ensure positions are not empty before sending RPC if (platformIDs.Length != arrangedPositions.Count || arrangedPositions.Count == 0) { Debug.LogError($"[PlatformSelection] ERROR: Mismatch! platformIDs: {platformIDs.Length}, positions: {arrangedPositions.Count}"); return; // Prevent sending incorrect RPC } for (int i = 0; i < m_Platforms.Count; i++) { m_Platforms[i].transform.position = arrangedPositions[i]; m_Platforms[i].RefreshCollider(); } // Send the data to all clients SyncPlatformsClientRpc(platformIDs, arrangedPositions.ToArray()); } private List ArrangePlatforms(List activePlatforms) { int platformCount = activePlatforms.Count; if (platformCount == 0) { Debug.LogError($"[ArrangePlatforms] No active platforms found!"); return new List(); } float startAngle = 90f; // Start from top List arrangedPositions = new List(); // Special case: If 2 platforms, place them opposite to each other if (platformCount == 2) { arrangedPositions.Add(centerPoint.position + new Vector3(shapeRadius, 0, 0)); // Right side arrangedPositions.Add(centerPoint.position + new Vector3(-shapeRadius, 0, 0)); // Left side } else { float angleStep = 360f / platformCount; for (int i = 0; i < platformCount; i++) { float angle = startAngle + (i * angleStep); float radians = angle * Mathf.Deg2Rad; Vector3 newPosition = new Vector3( centerPoint.position.x + shapeRadius * Mathf.Cos(radians), centerPoint.position.y, centerPoint.position.z + shapeRadius * Mathf.Sin(radians) ); arrangedPositions.Add(newPosition); Debug.Log($"[ArrangePlatforms] Assigned position {i}: {newPosition} to Platform ID: {activePlatforms[i].PlatformID.Value}"); } } Debug.Log($"[ArrangePlatforms] Successfully arranged {arrangedPositions.Count} platforms."); return arrangedPositions; } [ClientRpc] private void SyncPlatformsClientRpc(int[] platformIDs, Vector3[] positions) { Debug.Log($"[SyncPlatformsClientRpc] Received {platformIDs.Length} platforms to activate."); if (platformIDs.Length != positions.Length) { Debug.LogError($"[SyncPlatformsClientRpc] Data mismatch! Platform IDs: {platformIDs.Length}, Positions: {positions.Length}"); return; } m_Platforms = GetComponentsInChildren(true).ToList(); foreach (var platform in m_Platforms) { platform.gameObject.SetActive(false); } List activatedPlatforms = m_Platforms .Where(p => platformIDs.Contains(p.PlatformID.Value)) .OrderBy(p => p.PlatformID.Value) .ToList(); if (activatedPlatforms.Count != platformIDs.Length) { Debug.LogError($"[SyncPlatformsClientRpc] ERROR: Expected {platformIDs.Length} platforms but found {activatedPlatforms.Count} on the client."); return; } for (int i = 0; i < activatedPlatforms.Count; i++) { activatedPlatforms[i].gameObject.SetActive(true); activatedPlatforms[i].transform.position = positions[i]; // Force Collider Refresh activatedPlatforms[i].RefreshCollider(); Debug.Log($"[SyncPlatformsClientRpc] Activated Platform ID: {activatedPlatforms[i].PlatformID.Value} at {positions[i]}"); } Debug.Log($"[SyncPlatformsClientRpc] Successfully activated {activatedPlatforms.Count} platforms."); } public Platform FindNearestUnoccupiedPlatform(Vector3 position) { if (!IsServer) return null; return m_Platforms .Where(platform => !platform.IsOccupied) .OrderBy(platform => Vector3.Distance(position, platform.transform.position)) .FirstOrDefault(); } public bool AreAllPlatformsOccupied() { return m_Platforms.All(platform => platform.IsOccupied); } public Platform GetPlatformOccupiedByPlayer(ServerCharacter player) { return m_Platforms.FirstOrDefault(p => p.IsOccupied && p.GetOccupierId() == player.OwnerClientId); } public bool IsPlatformOccupied(Platform platform) { return platform.IsOccupied; } public Vector3 GetPlatformPosition(int platformId) { var platform = m_Platforms.FirstOrDefault(p => p.PlatformID.Value == platformId); return platform ? platform.transform.position : Vector3.zero; } public Platform GetPlatformById(int platformId) { return m_Platforms.FirstOrDefault(p => p.PlatformID.Value == platformId); } } }