I am attempting to add two timers:
- The first is a countdown timer, where people can join the server before the match starts. The controls should be disabled at this point
- The second is the game timer, which dictates how long the match should last, as well as send out other signals (sound effects, trigger power up drops, etc…).
My code is below. It has two problems:
- If a player joins after the host’s countdown timer is zero, the countdown timer UI always stays up and their controls are always disabled.
- The first time I run this code, the
Any advice is appreciated
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
using TMPro;
public class NetworkTimer : NetworkBehaviour
{
[Header("Game Timer")]
[SerializeField] private float timer = 45f;
[SerializeField] private TMP_Text timerText;
[Header("Countdown Timer")]
[SerializeField] private float countdownToGameTimer = 15f;
[SerializeField] private GameObject countdownTimerScreen;
[SerializeField] private TMP_Text countdownTimerText;
//[SerializeField] private ControlSignalSender controlSignalSender;
[SerializeField] private GameObject skipCountdownTimerButton;
[Header("Game Over Information")]
[SerializeField] private GameObject gameOverScreen;
//Signals for other scrips
public static event Action<NetworkTimer> OnTimerStart;
public static event Action<bool> OnGameStart;
public static event Action<NetworkTimer> OnFiveMinuteWarning;
public static event Action<NetworkTimer> OnOneMinuteWarning;
public static event Action<bool> OnGameOver;
//bools for if statements
private bool disableCountdownTimer = false;
private bool fiveMinuteWarning = false;
private bool oneMinuteWarning = false;
public override void OnNetworkSpawn()
{
if (!IsOwner) { return; }
//This is the signal to change the music to the correct track
OnTimerStart?.Invoke(this);
//This is the UI for the countdown screen
countdownTimerScreen.SetActive(true);
if (countdownToGameTimer <= 0)
{
//begin the game
countdownTimerScreen.SetActive(false);
//Send the signal to enable controls
OnGameStart?.Invoke(true);
Debug.Log("The timer is sending the signal from the Awake command to enable controls");
return;
}
}
private void Update()
{
if (disableCountdownTimer == false)
{
CountdownTimerToStart();
return;
}
//Update the time
GameTimer();
//Check the time, to see what events should happen
GameTimerOptions();
}
private void CountdownTimerToStart()
{
if (countdownToGameTimer <= 0)
{
return;
}
if (IsServer)
{
countdownToGameTimer -= Time.deltaTime;
UpdateCountdownTimerClientRpc(countdownToGameTimer);
}
}
[ClientRpc]
private void UpdateCountdownTimerClientRpc(float newTime)
{
//the client now has the new time
countdownToGameTimer = newTime;
//...and we update the display
UpdateCountdownTimerDisplay();
//Now, if the time is zero
if (countdownToGameTimer <= 0)
{
//begin the game
countdownTimerScreen.SetActive(false);
//Now, we make sure this script never runs again
disableCountdownTimer = true;
//This signal enables the controls for each player
OnGameStart?.Invoke(true);
Debug.Log("The timer is sending the signal to enable controls");
}
}
private void UpdateCountdownTimerDisplay()
{
int countdownSeconds = Mathf.FloorToInt(countdownToGameTimer % 60);
countdownTimerText.text = countdownSeconds.ToString("00");
}
public void StartNowButton()
{
countdownToGameTimer = 0f;
UpdateCountdownTimerClientRpc(0);
}
private void GameTimer()
{
//we don't need to run anything if the timer is done
if (timer <= 0)
{
return;
}
//If we are the server, we need to run the following code:
if (IsServer)
{
//decrease the timer, and...
timer -= Time.deltaTime;
//..update the timer on the client side
UpdateTimerClientRpc(timer);
return;
}
}
[ClientRpc]
private void UpdateTimerClientRpc(float newTime)
{
//the client now has the new time
timer = newTime;
//...and we update the display
UpdateTimerDisplay();
//Now, if the time is zero
if (timer <= 0)
{
//set the text to always say no time left
timerText.text = "Time Left: 00:00";
//...and set the game over screen
gameOverScreen.SetActive(true);
Time.timeScale = 0.0f;
//We are using this script to announce that the player has spawned
OnGameOver?.Invoke(this);
}
}
private void UpdateTimerDisplay()
{
float minutes = Mathf.FloorToInt(timer / 60);
float seconds = Mathf.FloorToInt(timer % 60);
timerText.text = string.Format("Time Left: {0:00}:{1:00}", minutes, seconds);
}
private void GameTimerOptions()
{
if (timer <= 300f && timer > 299f)
{
if (fiveMinuteWarning == false)
{
fiveMinuteWarning = true;
OnFiveMinuteWarning?.Invoke(this);
}
}
else if (timer >= 59f && timer < 60f)
{
if (oneMinuteWarning == false)
{
oneMinuteWarning = true;
OnOneMinuteWarning?.Invoke(this);
}
}
}
}