Well, I have a bool “charging” that should be active for a player’s gameObject in all the computers while the LocalPlayer holds spacebar, the code looks like this:
[SyncVar] bool charging;
int ammo;
int chargeSize;
void Update() {
if (charging) { Charge(); }
if (!isLocalPlayer) {return;}
FireMechanic();
}
void FireMechanic() {
if (Input.GetKey(KeyCode.Space) && ammo > 0) {
chargeSize++; //Irrelevant?
ammo--; //Irrelevant?
charging = true;
if (allowAmmoRegen) { allowAmmoRegen = false; }
}
if (Input.GetKeyUp(KeyCode.Space)) { //When spacebar releases
CmdFire(chargeSize);
charging = false;
chargeSize = 0;
allowAmmoRegen = true;
}
}
*Charging is irrelevant for CmdFire. It only activates Charge(), which just has a visual effect of some particle systems and stuff, is not altered in any other place of the script.
After running some Debug.Log()s, I realized only the host sets “charging” to true/false in every computer; The clients only have “charging” as true when needed on their computer, in every other computer it remains false always.
yep, that’s how sync vars work - only the server can change their values.
if you need a client to change a syncvar, it should send a command to the server, passing the new value as a parameter. the server would then update the syncvar in the command.
If you want to send data from Client → Server there are 2 ways
A: Command
B: MessageBase
So to sync a variable from a client to server + other clients it takes 2 steps.
Step1: Send data from client to server (2 options: Command or MessageBase)
Step2: Send data from server to all other clients (3 options: SyncVar, ClientRPC, or MessageBase)
If you decide to use SyncVars it becomes a little tricky because you must ignore the callbacks on the owner that set the value in the firstplace otherwise you’ll be fighting with the Server over control of it.
If you decide to use ClientRPC again the owner of the variable must ignore the message (or alternatively on send it to non-owner clients). Also late-connecting players will not get the latest up-to-date value when they connect.
I personally use MessageBase. But this gets extremely complicated as well.
try this - note the isServer checks I added. the server can set the sync var directly. non-servers send a command to the server, which then sets the sync var for everyone.
also I changed your first if (Input.GetKey()) to use GetKeyDown so you’re not spamming a command to the server every frame - this is a waste of bandwidth.
[SyncVar] bool charging;
int ammo;
int chargeSize;
void Update() {
if (charging) { Charge(); }
if (!isLocalPlayer) {return;}
FireMechanic();
}
void FireMechanic() {
if (Input.GetKeyDown(KeyCode.Space) && ammo > 0) {
chargeSize++; //Irrelevant?
ammo--; //Irrelevant?
if (isServer)
{
charging = true;
}
else
{
CmdCharging(true);
}
if (allowAmmoRegen) { allowAmmoRegen = false; }
}
if (Input.GetKeyUp(KeyCode.Space)) { //When spacebar releases
CmdFire(chargeSize);
if (isServer)
{
charging = false;
}
else
{
CmdCharging(false);
}
chargeSize = 0;
allowAmmoRegen = true;
}
}
[Command]
void CmdCharging(bool isCharging)
{
// note that this is only called on the server
charging = isCharging;
}