TL;DR
You are changing a [Networked]
variable locally in the client, as seen in your Object.HasInputAuthority
checking.
[Networked]
variables can only be changed by the StateAuthority
, then it will automatically be synced across clients.
You should find a way for the client to communicate with the host to change the [Networked]
variable. The easiest way would be via RPCs
from the client to the StateAuthority
.
The long answer
I am going to make a few assumptions about the requirements of your game, my apologies if I have misunderstood, but I hope this may still help you.
I will then clear up some concepts, so that at least we are in the same grounds before we can discuss your situation.
Then I will diagnose the problems in your code, and give you a suggestion of how I would write the code, which could hopefully be of some help to you.
Assumptions
For your game, I assume that
- Each player has a car
- Each car first moves at a constant speed
- Each player has a UI button
- When an individual player presses the UI button, that player's car will move faster
- You will eventually end up with different cars moving at different speeds
- Except for the UI, you expect the speeds of the cars and the visuals of the cars are synced across all clients, including the host.
For your code, I assume that
- Each car is a network object spawned by the host which has
StateAuthority
- Each car is given the
InputAuthority
of the player that controls the car
- Each car has at least the following components
Transform
NetworkObject
NetworkTransform
EntityScript
ControllerScript
- Each car has the visuals in a separate child game object and referenced in the
InterpolationTarget
of the NetworkObject
AppliedSpeed
is a public [Networked]
variable in the EntityScript
Concept Overview
Only StateAuthority
can change the network state, including [Networked]
variables. If you have a NetworkTransform
component on the GameObject
, the transform
of that GameObject
will then be also part of the network state. The transform
of the GameObject
in the host should be regarded as the single source of truth, and that will be synchronized across the clients.
So whether you are using NetworkInput
or RPC
, you have to ensure that it is the StateAuthority
doing the changes to the network state. Weird bugs will happen if only the client tries to change the network state.
Diagnosis
AppliedSpeed
is a [Networked]
variable. You are trying to change this variable in a if (Object.HasInputAuthority)
. This means that you are asking the InputAuthority
to change a [Networked]
variable locally. As mentioned above, only StateAuthority
can change [Networked]
variables.
This would most likely explain why the value would be applied for a split second then returning back to its original value. This is most likely because after the client changes the value [Networked]
variable locally, it becomes different than the value of the host. It will then self-correct itself to match the host, because the host is the absolute source of truth and only StateAuthority
can change the network state.
My Suggestion
Keep note that since this method uses RPCs
, RPCs
are not tick aligned and there is no prediction involved. Clients would probably feel some delay after clicking the button and seeing the car move faster. You may want to refactor and use NetworkInput
instead if it is critical to have everything tick-aligned and you would like to use prediction.
EntityScript.cs
public class EntityScript : NetworkBehaviour
{
[Networked] public float AppliedSpeed {get; set;}
// ...
public override void Spawned()
{
// Set the initial speed
AppliedSpeed = 15f;
}
public override void FixedUpdateNetwork()
{
transform.position += AppliedSpeed * transform.forward * Runner.DeltaTime;
}
// ...
}
ControllerScript.cs
public class ControllerScript : NetworkBehaviour
{
// I assume you would reference the EntityScript component here
[SerializedField] public EntityScript Controller;
// ...
// Called locally on the client from UI button press
public void OnButtonPress()
{
RPC_ChangeAppliedSpeed();
}
// Only StateAuthority can change networked variables
// So the client sends an RPC to the host to change the speed
[Rpc(RpcSources.All, RpcTargets.StateAuthority)]
private void RPC_ChangeAppliedSpeed()
{
// The networked variable will be synced automatically across all clients
Controller.AppliedSpeed += 10;
}
// ....
}
Hope this helps!
By this all people will know that you are my disciples, if you have love for one another. John 13:35 (ESV)