- Home /
How to synchronize a variable on the client and the host?
I am trying to make a countdown that would be the same on the client and the host. The problem is that when the host starts the game and the timer starts, if the client enters the game his timer will start at 60 secounds but the hosts won't change. it seems like both of them have their own variables, but i checked and they don't. I tryied using SincVar, but it doesn't work. My script:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine.Networking;
public class timer : NetworkBehaviour
{
int tr;
[SyncVar(hook = "OnTimeChange")]
int timeRemaining;
public string scene;
void Start()
{
if (isServer)
timeRemaining = 60;
tr = timeRemaining;
InvokeRepeating("decreaseTimeRemaining", 1.0f, 1.0f);
}
void decreaseTimeRemaining()
{
//Debug.Log(timeRemaining);
if (isServer)
{
Debug.Log("I am the server.");
//CmdSetTime(timeRemaining-1);
timeRemaining--;
}
}
public int getTimeRemaining()
{
Debug.Log("Get it" + tr);
return timeRemaining;
}
// [Command]
void CmdSetTime(int t)
{
Debug.Log("cmd set time:" + t);
t = timeRemaining;
t = tr;
}
void OnTimeChange(int t)
{
Debug.Log("On time change:" + t);
if (!isServer)
{
Debug.Log("Dumb times" + t);
timeRemaining = t;
tr = t;
}
}
}
Could anyone help? Than you in advance.
Sorry, I'm not even gonna try and read that code. Format it better for more responses.
I am sorry i am new to posting questions on here so i am not really sure if i am doing everything correctly. The secound try:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.Scene$$anonymous$$anagement;
using UnityEngine.Networking;
public class timer : NetworkBehaviour
{
int tr;
[SyncVar(hook = "OnTimeChange")]
int timeRemaining;
public string scene;
void Start()
{
if (isServer)
timeRemaining = 60;
tr = timeRemaining;
InvokeRepeating("decreaseTimeRemaining", 1.0f, 1.0f);
}
void decreaseTimeRemaining()
{
//Debug.Log(timeRemaining);
if (isServer)
{
Debug.Log("I am the server.");
//CmdSetTime(timeRemaining-1);
timeRemaining--;
}
}
public int getTimeRemaining()
{
Debug.Log("Get it" + tr);
return timeRemaining;
}
// [Command]
void CmdSetTime(int t)
{
Debug.Log("cmd set time:" + t);
t = timeRemaining;
t = tr;
}
void OnTimeChange(int t)
{
Debug.Log("On time change:" + t);
if (!isServer)
{
Debug.Log("Dumb times" + t);
timeRemaining = t;
tr = t;
}
}
}
$$anonymous$$uch better :) Formatting gives me a lot of trouble too, still. For next time; Proper procedure would be to EDIT your question, rather than post an answer. I have just edited the question for you, with the text from that answer, and am deleting converting that answer to a comment.
Okay, i understand and thank you for making it a comment. I don't think what i'm writing now is relevant to the question, so I am writing it as a reply to your comment, i hope that is alright.
Answer by LocalNoob · Sep 18, 2017 at 08:33 PM
Basically. If you only need the client to know when the timer is over just have the countdown happening on the server and then, once it is done send a TargetRpc(call from server to one specific client) to your client. If you wanna display a countdown on your client (like 1,2,3,4 using UI or something) you better off creating a countdown timer on the client which will only affect the graphics while the server timer (a different one) will handle doing stuff when it is over to prevent hacking! Why not have a timer synced between server and client??? Because it is a huge waste of bandwith constantly syncing stuff that can be done locally.
Create a timer on the server (secure) to handle important events and stuff
Create a timer on the client (not sync it from server, it is a waste of bandwith) to handle graphics only! Basically 1,2,3,4,5,6,7 bla bla bla.
Keep them in sync. When you need to reset them reset them both on server and client. It is much more efficient than syncvar (sending 32 bits(int) 10 times a second...).
Thank you for your answer, but i don't fully understand what you are talking about. $$anonymous$$y timer is a countdown, so i need it to count down, for example: 9, 8, 7, 6, 5, 4, and so on. Could you please include some sample script? Don't I need to use one script for each client and the server if I want to make a countdown on both of them seperately? And how do I connect them so they count in synch, but independantly?
using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.Networking;
public class Timer : NetworkBehaviour {
//Assign a player to who this timer corresponds (player controll is just my template class for player)
public PlayerControll player;
public Text countdownText;
//Value at which countdown starts
public float startValue = 10f;
//Timers
//ONLY FOR GRAPHICS
float clientTimer;
//FOR I$$anonymous$$PORTANT STUFF
float serverTimer;
public override void OnStartClient ()
{
clientTimer = startValue;
countdownText.text = startValue.ToString ();
}
public override void OnStartServer ()
{
serverTimer = startValue;
}
void Update(){
if (isLocalPlayer) {
//Client timer
clientTimer-=Time.deltaTime;
//Set the text graphic on client
countdownText.text = $$anonymous$$athf.FloorToInt (clientTimer).ToString ();
//Remove text graphic if timer reached 0
if (clientTimer <= 0) {
countdownText.text = string.Empty;
}
}
if (isServer) {
//Server timer
serverTimer-=Time.deltaTime;
if (serverTimer <= 0) {
//Reset server timer
serverTimer = startValue;
//and then reset client timer
//we can get connection to client(needed for TargetRPC) FRO$$anonymous$$ ITS PLAYER OBJECT ON THE SERVER
TargetResetClientTimer(player.connectionToClient);
DoStuff (); //on server
}
}
}
public void DoStuff(){
//ONLY DO DA$$anonymous$$AGE SPAWNING ETC HERE!
//and then reset client timer
//we can get connection to client FRO$$anonymous$$ ITS PLAYER OBJECT ON THE SERVER
TargetResetClientTimer(player.connectionToClient);
}
//Executes on ONE client to which NetworkConnection corresponds
//You can use a simple ClientRpc if this timer is the same to every player
//Using target rpc is good if there is a unique timer for each player
[TargetRpc]
void TargetResetClientTimer(NetworkConnection conn){
clientTimer = startValue;
}
}
I am sorry, but what do you mean by "template class for player", and where do i find out what it is for me? I did not need to know what that means until now, so I am clueless about it. Again I am sorry, since you are probably banging your head against the table right now.
Your answer
Follow this Question
Related Questions
[Networking] Changed text does not appear changed for players who just connected 0 Answers
How to get in sync two scripts if the Update () calls are random? 2 Answers
UNet Portal 2 Like Object Interaction Client to Server 1 Answer
An instance of type 'Script' is required to access non static member 'Variable' 1 Answer
How to make a variable increase at a constant rate? 1 Answer