Clean code with clientrpc enabling of platforms

dev-hazim
Ali Sharoz 2 weeks ago
parent 9f8cd0077b
commit 80b678cafb

@ -595,6 +595,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
PlatformID:
m_InternalValue: 0
--- !u!64 &249976107358570839 --- !u!64 &249976107358570839
MeshCollider: MeshCollider:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -788,6 +790,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
PlatformID:
m_InternalValue: 0
--- !u!64 &1223475210011116503 --- !u!64 &1223475210011116503
MeshCollider: MeshCollider:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -982,6 +986,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
PlatformID:
m_InternalValue: 0
--- !u!64 &1326862948614608681 --- !u!64 &1326862948614608681
MeshCollider: MeshCollider:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -1160,6 +1166,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
PlatformID:
m_InternalValue: 0
--- !u!64 &3169561862507413954 --- !u!64 &3169561862507413954
MeshCollider: MeshCollider:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -1338,6 +1346,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
PlatformID:
m_InternalValue: 0
--- !u!64 &5215249593494578416 --- !u!64 &5215249593494578416
MeshCollider: MeshCollider:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -1516,6 +1526,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
PlatformID:
m_InternalValue: 0
--- !u!64 &5615547279758710380 --- !u!64 &5615547279758710380
MeshCollider: MeshCollider:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -1694,6 +1706,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3} m_Script: {fileID: 11500000, guid: fbadb65558c0b1a48b58b765317ed874, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
PlatformID:
m_InternalValue: 0
--- !u!64 &7017483914677023159 --- !u!64 &7017483914677023159
MeshCollider: MeshCollider:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

@ -307,7 +307,7 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character
private void HandleOccupiedPlatform(Platform currentPlatform) private void HandleOccupiedPlatform(Platform currentPlatform)
{ {
var nearestPlatform = PlatformManager.Instance.FindNearestUnoccupiedPlatform(transform.position); var nearestPlatform = PlatformManager.Instance.GetNearestAvailablePlatform(transform.position);
if (nearestPlatform != null) if (nearestPlatform != null)
{ {
Debug.Log($"Platform {currentPlatform.PlatformID} is occupied. Moving to nearest Platform {nearestPlatform.PlatformID}."); 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) private void MoveToPlatform(Platform platform)
{ {
SetTargetPlatform(platform.PlatformID); int platformID = platform.PlatformID.Value; // Access the value of NetworkVariable<int>
var pltpos = PlatformManager.Instance.GetPlatformPosition(platform.PlatformID); SetTargetPlatform(platformID); // Set the target platform ID
pltpos.y = 0; var pltpos = PlatformManager.Instance.GetPlatformPosition(platformID); // Get platform position
pltpos.y = 0; // Reset Y-axis position for movement
Debug.Log($"Platform position: {pltpos}."); Debug.Log($"Platform position: {pltpos}.");
IsSwapping = true; 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() private void BecomeCrow()
{ {
ClearTargetPlatform(); ClearTargetPlatform();
@ -378,8 +389,8 @@ namespace Unity.BossRoom.Gameplay.GameplayObjects.Character
public void InitiateSwap(ServerCharacter initiatingPlayer, ServerCharacter targetPlayer) public void InitiateSwap(ServerCharacter initiatingPlayer, ServerCharacter targetPlayer)
{ {
var initiatingPlatform = PlatformManager.Instance.GetPlatformOccupiedByPlayer(initiatingPlayer); var initiatingPlatform = PlatformManager.Instance.GetPlayerPlatform(initiatingPlayer);
var targetPlatform = PlatformManager.Instance.GetPlatformOccupiedByPlayer(targetPlayer); var targetPlatform = PlatformManager.Instance.GetPlayerPlatform(targetPlayer);
if (initiatingPlatform == null || targetPlatform == null) if (initiatingPlatform == null || targetPlatform == null)
{ {

@ -9,184 +9,97 @@ namespace Unity.Multiplayer.Samples.BossRoom
[RequireComponent(typeof(Collider))] [RequireComponent(typeof(Collider))]
public class Platform : NetworkBehaviour public class Platform : NetworkBehaviour
{ {
public int PlatformID { get; private set; } public NetworkVariable<int> PlatformID = new NetworkVariable<int>(0);
public bool IsOccupied { get; private set; } public bool IsOccupied { get; private set; }
private NetworkVariable<ulong> OccupierId = new NetworkVariable<ulong>(0, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); private NetworkVariable<ulong> occupierId = new NetworkVariable<ulong>(0, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server);
private Collider m_PlatformCollider; private Collider platformCollider;
private Animator animator; private Animator animator;
private NetworkAnimator networkAnimator;
public void PauseAnimation() private void Awake()
{
platformCollider = GetComponent<Collider>();
if (!platformCollider.isTrigger)
platformCollider.isTrigger = true;
animator = GetComponent<Animator>();
}
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) if (IsOwner)
{ {
// Pause the animation locally
animator.speed = 0f; animator.speed = 0f;
PauseServerRpc();
// Inform the server to pause animation for all clients
PauseAnimationServerRpc();
} }
} }
public void ResumeAnimation() public void Resume()
{ {
if (IsOwner) if (IsOwner)
{ {
// Resume the animation locally
animator.speed = 1f; animator.speed = 1f;
ResumeServerRpc();
// Inform the server to resume animation for all clients
ResumeAnimationServerRpc();
} }
} }
[ServerRpc] [ServerRpc]
private void PauseAnimationServerRpc() private void PauseServerRpc() => PauseClientRpc();
{
// On the server, pause animation for all clients
PauseAnimationClientRpc();
}
[ClientRpc] [ClientRpc]
private void PauseAnimationClientRpc() private void PauseClientRpc() => animator.speed = 0f;
{
animator.speed = 0f;
}
[ServerRpc] [ServerRpc]
private void ResumeAnimationServerRpc() private void ResumeServerRpc() => ResumeClientRpc();
{
// On the server, resume animation for all clients
ResumeAnimationClientRpc();
}
[ClientRpc] [ClientRpc]
private void ResumeAnimationClientRpc() private void ResumeClientRpc() => animator.speed = 1f;
{
animator.speed = 1f;
}
private void Awake()
{
m_PlatformCollider = GetComponent<Collider>();
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<Animator>();
networkAnimator = GetComponent<NetworkAnimator>();
}
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) public void Occupy(ServerCharacter player)
{ {
if (!IsServer) if (!IsServer || IsOccupied) return;
{
Debug.LogError("Occupy can only be called on the server."); Pause();
return; bool giveScore = player.PreviousPlatformId != PlatformID.Value;
} int score = (player.TargetPlatformId == PlatformID.Value) ? 10 : 20;
PauseAnimation();
if (IsOccupied) if (giveScore) ScoreManager.Instance.AddPlayerScore(player.OwnerClientId, score);
{
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.");
}
}
IsOccupied = true; IsOccupied = true;
OccupierId.Value = player.OwnerClientId; occupierId.Value = player.OwnerClientId;
player.OnArrivalOnPlatform(PlatformID); player.OnArrivalOnPlatform(PlatformID.Value);
Debug.Log($"Platform {PlatformID} is now occupied by Player {player.OwnerClientId}.");
} }
public void Vacate(ServerCharacter player) public void Vacate(ServerCharacter player)
{ {
if (!IsServer) if (!IsServer || !IsOccupied || occupierId.Value != player.OwnerClientId) return;
{
Debug.LogError("Vacate can only be called on the server.");
return;
}
ResumeAnimation();
if (!IsOccupied || OccupierId.Value != player.OwnerClientId) Resume();
{
Debug.LogWarning($"Platform {PlatformID} is not occupied by Player {player.OwnerClientId}.");
return;
}
IsOccupied = false; IsOccupied = false;
OccupierId.Value = 0; occupierId.Value = 0;
player.OnLeavingPlatform(PlatformID); player.OnLeavingPlatform(PlatformID.Value);
Debug.Log($"Platform {PlatformID} is now vacated.");
} }
private void OnTriggerEnter(Collider other) private void OnTriggerEnter(Collider other)
{ {
if (!IsServer) return; if (IsServer && other.TryGetComponent<ServerCharacter>(out var player) && !IsOccupied)
Occupy(player);
if (other.TryGetComponent<ServerCharacter>(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;
} }
private void OnTriggerExit(Collider other) private void OnTriggerExit(Collider other)
{ {
if (!IsServer) return; if (IsServer && other.TryGetComponent<ServerCharacter>(out var player))
if (other.TryGetComponent<ServerCharacter>(out var player))
{
Vacate(player); Vacate(player);
if (OccupierId.Value == player.OwnerClientId)
player.OnLeavingPlatform(PlatformID);
}
} }
public ulong GetOccupierId() => occupierId.Value;
} }
} }

@ -1,3 +1,4 @@
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Unity.BossRoom.Gameplay.GameplayObjects.Character; using Unity.BossRoom.Gameplay.GameplayObjects.Character;
@ -9,112 +10,81 @@ namespace Unity.Multiplayer.Samples.BossRoom
public class PlatformManager : NetworkBehaviour public class PlatformManager : NetworkBehaviour
{ {
public static PlatformManager Instance; public static PlatformManager Instance;
public List<Platform> m_Platforms; private List<Platform> platforms;
public int numberOfPlayers = 2; // Number of players (n)
public float planeRadius = 4f; // Radius of the circular plane
private void Awake() private void Awake()
{ {
if (Instance != null && Instance != this) if (Instance != null && Instance != this)
{
Destroy(gameObject); Destroy(gameObject);
}
else else
{
Instance = this; Instance = this;
}
} }
private void Start() private void Start()
{ {
//if (IsServer) // Ensure only the server assigns IDs and initializes platforms = GetComponentsInChildren<Platform>(true).ToList();
{ if (IsServer) StartCoroutine(ServerSetup());
m_Platforms = GetComponentsInChildren<Platform>().ToList(); else StartCoroutine(ClientSetup());
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
);
} }
public Platform FindNearestUnoccupiedPlatform(Vector3 position) private IEnumerator ServerSetup()
{ {
if (!IsServer) yield return new WaitForSeconds(0.5f);
{ ActivatePlatformsServerRpc();
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();
} }
public bool AreAllPlatformsOccupied() private IEnumerator ClientSetup()
{ {
return m_Platforms.All(platform => platform.IsOccupied); yield return new WaitForSeconds(0.5f);
platforms = GetComponentsInChildren<Platform>(true).ToList();
} }
public bool AssignPlayerToPlatform(ServerCharacter player) [ServerRpc(RequireOwnership = false)]
private void ActivatePlatformsServerRpc()
{ {
if (!IsServer) int activeCount = PlayerPrefs.GetInt("NumberOfLobbyPlayers") - 1;
{ if (activeCount <= 0) return;
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;
}
public Platform GetPlatformOccupiedByPlayer(ServerCharacter player) platforms.ForEach(p => p.gameObject.SetActive(false));
{ for (int i = 0; i < activeCount; i++)
return m_Platforms.FirstOrDefault(p => p.IsOccupied && p.GetOccupierId() == player.OwnerClientId); 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<Platform>(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 IsServer ? platforms.Where(p => !p.IsOccupied).OrderBy(p => Vector3.Distance(position, p.transform.position)).FirstOrDefault() : null;
return platform ? platform.transform.position : Vector3.zero;
} }
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);
} }
} }

@ -101,7 +101,7 @@ public class ScoreManager : NetworkBehaviour
private IEnumerator ApplyCrowPenaltyCoroutine() 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) while (true)
{ {

Loading…
Cancel
Save