- Home /
Photon timer issue
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();
}
}
We can't see your modification, so it's hard to help. You want to set one bool value after a specified time? When does the timer start?
I edited the post and added some code. Right now, I have the timer set to 20 seconds, but in the final build, I'm going to set it to 180 seconds.
Answer by tobiass · Jan 14, 2015 at 11:34 AM
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);
}
}
I just have one more question. How do you sync the time over the network? When someone joins your room, their time is stays at 0 until the mc leaves. How do I fix this?
The code above does sync it over the network. The room properties are synced. When someone joins, that client should call OnPhotonCustomRoomPropertiesChanged and set timeToStart immediately. Afaik, it does this.
Your answer
Follow this Question
Related Questions
Updating multiplayer map on joining 1 Answer
Unity networking tutorial? 6 Answers
Photon Cloud, Multiplayer Damage script 0 Answers
Networking - Move all players to a position? (Photon) 1 Answer