- Home /
Networking: How to get server values from clients to keep a chronometer in sync
I have a multiplayer testing project with Unity 2017.2 in which all player objects move on their own in tests. Now I want to adapt some vars that worked on single player to the multiplayer version:
float timer = 600.0f;
float init_time = 0.0f;
bool time_running = false;
void Update () {
if (time_running) {
timer -= Time.deltaTime;
}
if (init_time < 5.0f) {
init_time += Time.deltaTime;
}
if (init_time >= 5.0f) {
time_running = true;
}
}
The adaptations I want to perform are:
Server decides when the timer starts counting
When client connects (either the game started or not) get all the variables the same value as the server, and keep performing
Time.deltaTime
sums on its own.
On single player, this logic worked on an empty GameObject which vars were getted by any GameObject with MonoBehaviour script which might need reading the timer
(for example, to update GUI display), using references with GameObject.Find()
and similar functions in order to retrieve a reference to the script component and get the values.
Now for Multiplayer, I wonder... which would be the way to make this work as expected (the features listed above)? I mean, which object/s should own these variables and make them work properly?
I have tried all kind of experiments with non-player NetworkBehaviour objects and make trial-and-error with [SyncVar]
attributes on variables I want to sync: but I don't accomplish them to be the same value when testing with two players. I have also made some trial-and-error with [ClientRPC]
but couldn't make any difference. I am not sure if I get how these attributes work though, even if I have read all kind of available documentation about them, and how NetworkBehaviour works. I even tried some experiments with an extended NetworkManager
class but didn't achieve anything different.
I am completely confused about:
Which objects should own the variables
How should they manipulate them in order to guarantee server dictates which value they must have when client player joins
How should I make MonoBehaviour objects get references to the values (to display them in GUI, for example)
I've not used Unity networking stuff, so I'm not going to be able to help with syntax stuff (how exactly to "get a variable from the server", for example). Not sure if it will help, but, I can tell you how I would structure the data and server-client relationship to do something like this.
"Which objects should own the variables"
I'd expect the server to store the "authoritative" timer. And, an "authoritative" running_flag,(a bool that states if the timer is running).
The Player/client will store a "non-authoritative" timer, and "non-authoritative" running_flag.
"How should they manipulate them in order to guarantee server dictates which value they must have when client player joins"
When they join the game, players/clients will request from the server, the "authoritative" values and store them in their own "non-authoritative" variables.
During the player's update, they would check if their non-authoritative running_flag is true:
-if so, they can update their version of the timer. (You may want each player to occasionally (every second or two) check the authoritative timer, to make sure they don't stray off. I'm not sure if the server can STOP the timer, but if so, you may need to occasionally check with the server for that too.)
-if not, they can contact the server and request the authoritative version of the running_flag, to see if it is now true ( and if so, store the authoritative values in its own, non-authoritative variables.)
"How should I make $$anonymous$$onoBehaviour objects get references to the values (to display them in GUI, for example) "
Display the non-authoritative values that you have stored in the player/client, just as you do now.
Am I getting this right? The server should start the timer after 5 seconds. If a client connects, he gets the current time and starts his own timer ignoring any update the server is providing from then on?
If that's correct so far, two more questions arise:
- What's with players connecting prior to the 5 seconds start delay? - What's with the players local time straying off over time compared to the servers?
Essentially, the 5 seconds timer is for delaying game start.
What I try to achieve is to keep the three variables in sync across all clients. In other words:
The server will rule both timers, and the
time_running
boolean.The client gets the three variables when player joins the game, getting the server current values.
As from there on, they are "supposed to be the same" (stuff migh happen, but let's ignore network delays and stuff for now), then clients will keep running their own chronos from there on (to save bandwidth).
Anyways, the server must make the final decision about if the game's over or not (but that matter is out of the scope of this question)