Commit 39dc1546 by alsunj

Add update timers about remaining players and game start

parent f32f751b
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using TMPro;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using Unity.Networking.Transport;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class ClientConnectionManager : MonoBehaviour
public class ClientConnectionManager : NetworkBehaviour
{
[SerializeField] private GameObject _WaitingPlayerPanel;
[SerializeField] private TextMeshProUGUI _waitingText;
//[SerializeField] private GameObject _confirmQuitPanel;
[SerializeField] private GameObject _countdownPanel;
[SerializeField] private TextMeshProUGUI _countdownText;
[SerializeField] private GameObject _connectionPanel;
[SerializeField] private TMP_InputField _addressField;
[SerializeField] private TMP_InputField _portField;
[SerializeField] private TMP_Dropdown _connectionModeDropdown;
......@@ -23,14 +33,22 @@ public class ClientConnectionManager : MonoBehaviour
[SerializeField] private int _gameStartCountDownTime;
[SerializeField] private float _slimeSpawnCooldownTime;
[SerializeField] private float _rogueSpawnCooldownTime;
[SerializeField] private GameObject playerPrefab; // Set the name in the Inspector
[SerializeField] private int _startGameCountdownTimer = 10;
private GameObject gameConfigHolder;
private List<ulong> connectedClientIds = new List<ulong>(); // Use a List for dynamic size
private ushort Port => ushort.Parse(_portField.text);
private int PlayerAmount => int.Parse(_playerAmountField.text);
private int RogueEnemyAmount => int.Parse(_RogueEnemyAmountField.text);
private int SlimeEnemyAmount => int.Parse(_SlimeEnemyAmountField.text);
private string Address => _addressField.text;
private bool _timerRunning = false;
private int _serverCountdown;
private void OnEnable()
{
_connectionModeDropdown.onValueChanged.AddListener(OnConnectionModeChanged);
......@@ -74,24 +92,10 @@ public class ClientConnectionManager : MonoBehaviour
}
private async void OnButtonConnect()
private void OnButtonConnect()
{
GameObject networkManagerObject = NetworkManager.Singleton.gameObject;
// AsyncOperation loadOperation = SceneManager.LoadSceneAsync("SC", LoadSceneMode.Additive);
// while (!loadOperation.isDone)
// {
// await System.Threading.Tasks.Task.Yield();
// }
//
// Scene gameScene = SceneManager.GetSceneByName("SC");
//
// SceneManager.MoveGameObjectToScene(networkManagerObject, gameScene);
//
// SceneManager.SetActiveScene(gameScene);
//
// SceneManager.UnloadSceneAsync("ConnectionScene");
_connectionPanel.SetActive(false);
_WaitingPlayerPanel.SetActive(true);
switch (_connectionModeDropdown.value)
{
case 0:
......@@ -114,7 +118,7 @@ public class ClientConnectionManager : MonoBehaviour
GameStartConfig gameStartConfig = cameStartConfigHolder.AddComponent<GameStartConfig>();
gameStartConfig.PlayerAmount = PlayerAmount;
GameObject gameConfigHolder = new GameObject("GameConfigHolder");
gameConfigHolder = new GameObject("GameConfigHolder");
GameDataConfig configComponent = gameConfigHolder.AddComponent<GameDataConfig>();
configComponent.RogueEnemyAmount = RogueEnemyAmount;
......@@ -125,26 +129,180 @@ public class ClientConnectionManager : MonoBehaviour
private void StartServer()
{
UnityTransport transport = NetworkManager.Singleton.GetComponent<UnityTransport>();
if (transport != null)
{
transport.SetConnectionData(Address, Port);
NetworkManager.Singleton.GetComponent<UnityTransport>().SetConnectionData(Address, Port);
NetworkManager.Singleton.StartHost();
NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnected;
NetworkManager.Singleton.OnConnectionEvent += OnNetworkConnectionEvent;
connectedClientIds.Add(NetworkManager.Singleton.LocalClientId);
CheckConnectedClientAmount();
}
private void OnNetworkConnectionEvent(NetworkManager networkManager, ConnectionEventData connectionEvent)
{
if (IsServer)
{
if (connectionEvent.EventType == ConnectionEvent.ClientConnected)
{
Debug.Log($"Client connected with ID: {connectionEvent.ClientId}");
connectedClientIds.Add(connectionEvent.ClientId);
Debug.Log($"Connected Client Count: {connectedClientIds.Count}");
// Update your UI here based on connectedClientIds.Count
}
else if (connectionEvent.EventType == ConnectionEvent.ClientDisconnected)
{
Debug.Log($"Client disconnected with ID: {connectionEvent.ClientId}");
connectedClientIds.Remove(connectionEvent.ClientId);
Debug.Log($"Connected Client Count: {connectedClientIds.Count}");
}
CheckConnectedClientAmount();
}
}
//must be executed only by the server
private void CheckConnectedClientAmount()
{
if (connectedClientIds.Count >= PlayerAmount && !_timerRunning)
{
BeginGameStart();
}
else
{
Debug.LogError("Unity Transport component not found on the NetworkManager!");
UpdatePlayerRemainingTextClientRpc(PlayerAmount - connectedClientIds.Count);
}
}
//must be executed only by the server
private void BeginGameStart()
{
_serverCountdown = _startGameCountdownTimer;
StartCoroutine(StartGameTimer());
BeginGameStartClientRpc(_serverCountdown); // Initial notification
}
//must be executed only by the server
private IEnumerator StartGameTimer()
{
_timerRunning = true;
OpenCountDownPanelClientRpc();
PrepareGameLoadSceneForServerAsync();
while (_serverCountdown > 0)
{
yield return new WaitForSeconds(1f);
_serverCountdown--;
UpdateCountdownClientRpc(_serverCountdown); // Update clients with the current value
}
UnloadSceneClientRpc("ConnectionScene");
SpawnPlayers();
Destroy(gameObject);
}
[ClientRpc]
private void UnloadSceneClientRpc(string sceneName)
{
SceneManager.UnloadSceneAsync(sceneName);
}
private void CloseGameStartPanel()
{
_countdownPanel.SetActive(false);
}
private void PrepareGameLoadSceneForServerAsync()
{
NetworkManager.Singleton.SceneManager.LoadScene("SC", LoadSceneMode.Additive);
NetworkManager.Singleton.SceneManager.OnLoadEventCompleted += OnSceneLoadCompleted;
}
private void OnSceneLoadCompleted(string scenename, LoadSceneMode loadscenemode, List<ulong> clientscompleted,
List<ulong> clientstimedout)
{
if (IsServer)
{
Scene gameScene = SceneManager.GetSceneByName(scenename);
SceneManager.MoveGameObjectToScene(NetworkManager.Singleton.gameObject, gameScene);
SceneManager.MoveGameObjectToScene(gameConfigHolder, gameScene);
SceneManager.SetActiveScene(gameScene);
CheckSceneLoadCompletion(connectedClientIds, clientscompleted, clientstimedout);
NetworkManager.Singleton.SceneManager.OnLoadEventCompleted -= OnSceneLoadCompleted;
}
}
private void CheckSceneLoadCompletion(List<ulong> initialConnectedClientIds, List<ulong> clientsCompleted,
List<ulong> clientsTimedOut)
{
foreach (ulong clientId in initialConnectedClientIds)
{
if (clientsCompleted.Contains(clientId))
{
Debug.Log($"[Server] Client ID {clientId} successfully loaded the scene.");
}
else if (clientsTimedOut.Contains(clientId))
{
Debug.LogWarning($"[Server] Client ID {clientId} timed out during scene load.");
}
else
{
Debug.LogWarning(
$"[Server] Client ID {clientId} from initial connection list neither completed nor timed out during scene load. This might indicate a disconnection or other issue.");
}
}
}
[ClientRpc]
private void BeginGameStartClientRpc(int initialCountdownValue)
{
_WaitingPlayerPanel.SetActive(false);
_countdownPanel.SetActive(true);
_countdownText.text = initialCountdownValue.ToString();
}
[ClientRpc]
private void UpdatePlayerRemainingTextClientRpc(int remainingPlayers)
{
var playersText = remainingPlayers == 1 ? "player" : "players";
_waitingText.text = $"Waiting for {remainingPlayers} more {playersText} to join...";
}
private void OnClientConnected(ulong obj)
[ClientRpc]
private void UpdateCountdownClientRpc(int currentCountdownValue)
{
GameStartConfig.Instance.IncrementConnectedPlayers();
Debug.Log(GameStartConfig.Instance.GetConnectedPlayers() + "amount connected");
_countdownText.text = currentCountdownValue.ToString();
}
[ClientRpc]
private void OpenCountDownPanelClientRpc()
{
CloseGameStartPanel();
}
private void SpawnPlayers()
{
foreach (ulong clientId in connectedClientIds)
{
Vector3 spawnPosition = Vector3.zero;
Quaternion spawnRotation = Quaternion.identity;
GameObject spawnedPlayer = Instantiate(playerPrefab, spawnPosition, spawnRotation);
NetworkObject networkObject = spawnedPlayer.GetComponent<NetworkObject>();
if (networkObject != null)
{
networkObject.SpawnAsPlayerObject(clientId, true);
}
else
{
Destroy(spawnedPlayer);
Debug.LogError($"[Server] Failed to get NetworkObject on spawned player for client {clientId}.");
}
}
}
private void StartClient()
{
UnityTransport transport = NetworkManager.Singleton.GetComponent<UnityTransport>();
......@@ -152,16 +310,12 @@ public class ClientConnectionManager : MonoBehaviour
{
transport.SetConnectionData(Address, Port);
NetworkManager.Singleton.StartClient();
}
else
{
Debug.LogError("Unity Transport component not found on the NetworkManager!");
}
}
private void OnDestroy()
{
NetworkManager.Singleton.OnClientConnectedCallback -= OnClientConnected;
}
}
// would be ideal to reject connections if the game has already started but unity does not have a way to do this
// one way would be rejecting the connections in the OnNetworkConnectionEvent method or setting strange values in server connection data
\ No newline at end of file
......@@ -281,6 +281,7 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 529219306}
- component: {fileID: 529219308}
- component: {fileID: 529219307}
m_Layer: 0
m_Name: ConnectionManager
......@@ -316,6 +317,12 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 073290f5692bc3e468889c25d8a4f3e4, type: 3}
m_Name:
m_EditorClassIdentifier:
ShowTopMostFoldoutHeaderGroup: 1
_WaitingPlayerPanel: {fileID: 1405885247}
_waitingText: {fileID: 1216956540}
_countdownPanel: {fileID: 2138866768}
_countdownText: {fileID: 1593960351}
_connectionPanel: {fileID: 1517982078}
_addressField: {fileID: 776996437}
_portField: {fileID: 1656278101}
_connectionModeDropdown: {fileID: 1746526225}
......@@ -329,6 +336,33 @@ MonoBehaviour:
_gameStartCountDownTime: 2
_slimeSpawnCooldownTime: 0.1
_rogueSpawnCooldownTime: 1
playerPrefab: {fileID: 7039287367920326276, guid: 702bb31d143eeaa4792be36b28160445, type: 3}
_startGameCountdownTimer: 10
--- !u!114 &529219308
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 529219305}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 1225910293
InScenePlacedSourceGlobalObjectIdHash: 0
DeferredDespawnTick: 0
Ownership: 1
AlwaysReplicateAsRoot: 0
SynchronizeTransform: 1
ActiveSceneSynchronization: 0
SceneMigrationSynchronization: 1
SpawnWithObservers: 1
DontDestroyWithOwner: 0
AutoObjectParentSync: 1
SyncOwnerTransformWhenParented: 1
AllowOwnerToParent: 0
--- !u!114 &776996437 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 5737202750316455812, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
......@@ -345,6 +379,17 @@ GameObject:
m_CorrespondingSourceObject: {fileID: 856385695763539090, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
m_PrefabInstance: {fileID: 5176588386858245479}
m_PrefabAsset: {fileID: 0}
--- !u!114 &1216956540 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 5516049037900670687, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
m_PrefabInstance: {fileID: 5176588386858245479}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1001 &1233896419
PrefabInstance:
m_ObjectHideFlags: 0
......@@ -403,6 +448,14 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 7022544978650153336, guid: f6024856153867c408043e682ddcac1e, type: 3}
propertyPath: NetworkConfig.ForceSamePrefabs
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7022544978650153336, guid: f6024856153867c408043e682ddcac1e, type: 3}
propertyPath: NetworkConfig.ConnectionApproval
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7022544978650153336, guid: f6024856153867c408043e682ddcac1e, type: 3}
propertyPath: NetworkConfig.EnableSceneManagement
value: 1
objectReference: {fileID: 0}
m_RemovedComponents: []
......@@ -421,6 +474,16 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 2da0c512f12947e489f739169773d7ca, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1405885247 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 8843338606411401250, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
m_PrefabInstance: {fileID: 5176588386858245479}
m_PrefabAsset: {fileID: 0}
--- !u!1 &1517982078 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 4013928434927110539, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
m_PrefabInstance: {fileID: 5176588386858245479}
m_PrefabAsset: {fileID: 0}
--- !u!1 &1544296584 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 7340525383002667710, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
......@@ -437,6 +500,17 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 2da0c512f12947e489f739169773d7ca, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &1593960351 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 155486888234904070, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
m_PrefabInstance: {fileID: 5176588386858245479}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &1643671676 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 3534326167216121825, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
......@@ -549,6 +623,11 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7b743370ac3e4ec2a1668f5455a8ef8a, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &2138866768 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 5941479522577420387, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
m_PrefabInstance: {fileID: 5176588386858245479}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &5176588386858245479
PrefabInstance:
m_ObjectHideFlags: 0
......@@ -825,6 +904,10 @@ PrefabInstance:
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5941479522577420387, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6271467599557108680, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
propertyPath: m_AnchorMax.y
value: 0
......@@ -921,6 +1004,14 @@ PrefabInstance:
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8843338606411401250, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
propertyPath: m_Name
value: WaitingPlayerPanel
objectReference: {fileID: 0}
- target: {fileID: 8843338606411401250, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8875326252354947531, guid: 72327351aa28fbe4fb4c16c3d17e4de5, type: 3}
propertyPath: m_Pivot.x
value: 0
......@@ -1010,8 +1101,8 @@ PrefabInstance:
SceneRoots:
m_ObjectHideFlags: 0
m_Roots:
- {fileID: 529219306}
- {fileID: 321845824}
- {fileID: 1670129068}
- {fileID: 529219306}
- {fileID: 1233896419}
- {fileID: 1670129068}
- {fileID: 5176588386858245479}
......@@ -256,7 +256,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!4 &863308619
Transform:
m_ObjectHideFlags: 0
......@@ -279,7 +279,7 @@ MonoBehaviour:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 863308618}
m_Enabled: 1
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9484dda6623b48b4999b76e13e6dd9cc, type: 3}
m_Name:
......
......@@ -82,7 +82,7 @@ PlayerSettings:
androidApplicationEntry: 2
defaultIsNativeResolution: 1
macRetinaSupport: 1
runInBackground: 0
runInBackground: 1
muteOtherAudioSources: 0
Prepare IOS For Recording: 0
Force IOS Speakers When Recording: 0
......
......@@ -4,63 +4,9 @@
QualitySettings:
m_ObjectHideFlags: 0
serializedVersion: 5
m_CurrentQuality: 1
m_CurrentQuality: 0
m_QualitySettings:
- serializedVersion: 4
name: Mobile
pixelLightCount: 2
shadows: 2
shadowResolution: 1
shadowProjection: 1
shadowCascades: 2
shadowDistance: 40
shadowNearPlaneOffset: 3
shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 0
skinWeights: 2
globalTextureMipmapLimit: 0
textureMipmapLimitSettings: []
anisotropicTextures: 1
antiAliasing: 0
softParticles: 0
softVegetation: 1
realtimeReflectionProbes: 0
billboardsFaceCameraPosition: 1
useLegacyDetailDistribution: 1
adaptiveVsync: 0
vSyncCount: 0
realtimeGICPUUsage: 100
adaptiveVsyncExtraA: 0
adaptiveVsyncExtraB: 0
lodBias: 1
maximumLODLevel: 0
enableLODCrossFade: 1
streamingMipmapsActive: 0
streamingMipmapsAddAllCameras: 1
streamingMipmapsMemoryBudget: 512
streamingMipmapsRenderersPerFrame: 512
streamingMipmapsMaxLevelReduction: 2
streamingMipmapsMaxFileIORequests: 1024
particleRaycastBudget: 256
asyncUploadTimeSlice: 2
asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 11400000, guid: 5e6cbd92db86f4b18aec3ed561671858,
type: 2}
terrainQualityOverrides: 0
terrainPixelError: 1
terrainDetailDensityScale: 1
terrainBasemapDistance: 1000
terrainDetailDistance: 80
terrainTreeDistance: 5000
terrainBillboardStart: 50
terrainFadeLength: 5
terrainMaxTrees: 50
excludedTargetPlatforms:
- Standalone
- serializedVersion: 4
name: PC
pixelLightCount: 2
shadows: 2
......@@ -101,8 +47,7 @@ QualitySettings:
asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 11400000, guid: 4b83569d67af61e458304325a23e5dfd,
type: 2}
customRenderPipeline: {fileID: 11400000, guid: 4b83569d67af61e458304325a23e5dfd, type: 2}
terrainQualityOverrides: 0
terrainPixelError: 1
terrainDetailDensityScale: 1
......@@ -116,19 +61,4 @@ QualitySettings:
- Android
- iPhone
m_TextureMipmapLimitGroupNames: []
m_PerPlatformDefaultQuality:
Android: 0
GameCoreScarlett: 1
GameCoreXboxOne: 1
Lumin: 0
Nintendo Switch: 1
PS4: 1
PS5: 1
Server: 0
Stadia: 0
Standalone: 1
WebGL: 0
Windows Store Apps: 0
XboxOne: 0
iPhone: 0
tvOS: 0
m_PerPlatformDefaultQuality: {}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment