I’m working on a multiplayer game, and I’m using Photon+ for the networking. I have a modified version of the InRoomRoundTimer script. I’m trying to have it tell a Boolean value to set to true. But instead, the timer resets and the value isn’t called. How can I fix this? Thanks for the help!
Here’s the code:
using UnityEngine;
using ExitGames.Client.Photon;
public class MatchTimer : MonoBehaviour {
public int SecondsPerMatch = 5; // time per round/turn
public double StartTime; // this should could also be a private. i just like to see this in inspector
public Rect TextPos = new Rect(0, 80, 150, 300); // default gui position. inspector overrides this!
public double timeRemaining = 20;
private bool startRoundWhenTimeIsSynced; // used in an edge-case when we wanted to set a start time but don't know it yet.
private const string StartTimeKey = "st"; // the name of our "start time" custom property.
public bool showResults = false;
private void StartRoundNow()
{
// in some cases, when you enter a room, the server time is not available immediately.
// time should be 0.0f but to make sure we detect it correctly, check for a very low value.
if (PhotonNetwork.time < 0.0001f)
{
// we can only start the round when the time is available. let's check that in Update()
startRoundWhenTimeIsSynced = true;
showResults = true;
return;
}
startRoundWhenTimeIsSynced = false;
showResults = false;
ExitGames.Client.Photon.Hashtable startTimeProp = new Hashtable(); // only use ExitGames.Client.Photon.Hashtable for Photon
// startTimeProp[StartTimeKey] = PhotonNetwork.time;
// PhotonNetwork.room.SetCustomProperties(startTimeProp); // implement OnPhotonCustomRoomPropertiesChanged(Hashtable propertiesThatChanged) to get this change everywhere
}
/// <summary>Called by PUN when this client entered a room (no matter if joined or created).</summary>
public void OnJoinedRoom()
{
if (PhotonNetwork.isMasterClient)
{
// this.StartRoundNow();
showResults = false;
}
else
{
// as the creator of the room sets the start time after entering the room, we may enter a room that has no timer started yet
Debug.Log("StartTime already set: " + PhotonNetwork.room.customProperties.ContainsKey(StartTimeKey));
}
}
void Start()
{
// StartRoundNow();
// showResults = true;
}
/// <summary>Called by PUN when new properties for the room were set (by any client in the room).</summary>
public void OnPhotonCustomRoomPropertiesChanged(Hashtable propertiesThatChanged)
{
if (propertiesThatChanged.ContainsKey(StartTimeKey))
{
//StartTime = (double)propertiesThatChanged[StartTimeKey];
//showResults = true;
}
}
/// <remarks>
/// In theory, the client which created the room might crash/close before it sets the start time.
/// Just to make extremely sure this never happens, a new masterClient will check if it has to
/// start a new round.
/// </remarks>
public void OnMasterClientSwitched(PhotonPlayer newMasterClient)
{
if (!PhotonNetwork.room.customProperties.ContainsKey(StartTimeKey))
{
Debug.Log("The new master starts a new round, cause we didn't start yet.");
// this.StartRoundNow();
}
}
void Update()
{
if (startRoundWhenTimeIsSynced)
{
// showResults = true;
// this.StartRoundNow(); // the "time is known" check is done inside the method.
}
if (timeRemaining <= 0.0001f)
{
timeRemaining = 0;
showResults = true;
}
/* if (PhotonNetwork.time < 0.0001f)
{
showResults = true;
}*/
}
public void OnGUI()
{
// alternatively to doing this calculation here:
// calculate these values in Update() and make them publicly available to all other scripts
double elapsedTime = (PhotonNetwork.time - StartTime);
double remainingTime = SecondsPerMatch - (elapsedTime % SecondsPerMatch);
// int turn = (int)(elapsedTime / SecondsPerMatch);
timeRemaining = remainingTime;
// simple gui for output
GUILayout.BeginArea(new Rect(Screen.width - 570, 0, 200, 40));
// GUILayout.Label(string.Format("elapsed: {0:0.000}", elapsedTime));
GUILayout.Box(string.Format("Time remaining: {0:0}", remainingTime));
// GUILayout.Label(string.Format("turn: {0:0}", turn));
/* if (GUILayout.Button("new round"))
{
this.StartRoundNow();
}*/
GUILayout.EndArea();
if (timeRemaining <= 0.0001f)
showResults = true;
if (showResults)
{
ShowResults();
}
}
void ShowResults()
{
GUILayout.BeginArea(new Rect((Screen.width - 400) / 2, (Screen.height - 300) / 2, 400, 300));
GUILayout.Label("Match results:");
foreach (PhotonPlayer pl in PhotonNetwork.playerList)
{
GUILayout.BeginHorizontal();
GUILayout.Label("Name: " + pl.name);
GUILayout.Label("Kills: " + pl.GetScore());
GUILayout.Label("Team: " + pl.GetTeam());
GUILayout.EndHorizontal();
}
GUILayout.Label("After seeing your score, you may leave and return to the lobby");
GUILayout.EndArea();
}
}
tobiass
2
I don’t know exactly what you want to achieve but if you want a bool to be true after a certain time in a room, then why don’t you just store a property when this happens? It’s current time + duration.
All clients can check if it’s later than the time you stored.
I skipped most of the GUI stuff but this is how I’d do it.
using System.IO;
using ExitGames.Client.Photon;
using Photon;
using UnityEngine;
public class MatchTimer : PunBehaviour
{
private const string TimeToStartProp = "st";
private double timeToStart = 0.0f;
public double SecondsBeforeStart = 20.0f; // set in inspector
public bool IsItTimeYet
{
get { return IsTimeToStartKnown && PhotonNetwork.time > this.timeToStart; }
}
public bool IsTimeToStartKnown
{
get { return this.timeToStart > 0.001f; }
}
public double SecondsUntilItsTime
{
get
{
if (this.IsTimeToStartKnown)
{
double delta = this.timeToStart - PhotonNetwork.time;
return (delta > 0.0f) ? delta : 0.0f;
}
else
{
return 0.0f;
}
}
}
void Update()
{
if (PhotonNetwork.isMasterClient)
{
// the master client checks if a start time is set. we check a min value
if (!this.IsTimeToStartKnown && PhotonNetwork.time > 0.0001f)
{
// no startTime set for room. calculate and set it as property of this room
this.timeToStart = PhotonNetwork.time + SecondsBeforeStart;
Hashtable timeProps = new Hashtable() {{TimeToStartProp, this.timeToStart}};
PhotonNetwork.room.SetCustomProperties(timeProps);
}
}
}
public override void OnPhotonCustomRoomPropertiesChanged(Hashtable propertiesThatChanged)
{
if (propertiesThatChanged.ContainsKey(TimeToStartProp))
{
this.timeToStart = (double) propertiesThatChanged[TimeToStartProp];
Debug.Log("Got StartTime: " + this.timeToStart + " is it time yet?! " + this.IsItTimeYet);
}
}
void OnGUI()
{
GUILayout.Label("Is it time yet: " + this.IsItTimeYet);
GUILayout.Label("Seconds until it's time: " + (float)this.SecondsUntilItsTime);
}
}
Sorry for re-opening this, but when I want to some object be SetActive when time is 0, how to do this? I used this script above from @tobiass