Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/jackmawer/JacksWorld. An abandoned mini-project that I created while learning to use Unity with networking.
Something went wrong. Try again.
4.7 kB · 114 lines
C#
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115using ExitGames.Client.Photon;using UnityEngine;
/// <summary>/// Simple script that uses a property to sync a start time for a multiplayer game./// </summary>/// <remarks>/// When entering a room, the first player will store the synchronized timestamp. /// You can't set the room's synchronized time in CreateRoom, because the clock on the Master Server/// and those on the Game Servers are not in sync. We use many servers and each has it's own timer./// /// Everyone else will join the room and check the property to calculate how much time passed since start./// You can start a new round whenever you like./// /// Based on this, you should be able to implement a synchronized timer for turns between players./// </remarks>public class InRoomRoundTimer : MonoBehaviour{ public int SecondsPerTurn = 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!
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.
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; return; } startRoundWhenTimeIsSynced = 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(); } 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)); } }
/// <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]; } }
/// <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) { this.StartRoundNow(); // the "time is known" check is done inside the method. } }
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 = SecondsPerTurn - (elapsedTime % SecondsPerTurn); int turn = (int)(elapsedTime / SecondsPerTurn);
// simple gui for output GUILayout.BeginArea(TextPos); GUILayout.Label(string.Format("elapsed: {0:0.000}", elapsedTime)); GUILayout.Label(string.Format("remaining: {0:0.000}", remainingTime)); GUILayout.Label(string.Format("turn: {0:0}", turn)); if (GUILayout.Button("new round")) { this.StartRoundNow(); } GUILayout.EndArea(); }}