I am currently developing a multiplayer racing game in Unity that utilizes Photon Fusion. In all the documentation, Photon Fusion uses the Input methods to sync the positions of the players and everything under FixedUpdateNetwork(). But in my game, I just need to Network a float variable, that changes based on players input through a UI button. So basically, the car will move forward at a fixed speed at first. And based on the players input, the speed varies for each player.
I first attempted to sync the variable using [Networked]. The Host variable only gets synced across builds. But, not from clients to the host. The client's value never gets updated in either of the client's car or in the host game. I get an update that the value is applied to the client's car for a split second before it glitches and returns to its normal position. This only occurs in the client build. And then I tried the RPC method. It worked fine, but sometimes the client's car moves way faster than the hosts. It is recommended in the Photon Fusion documentation not to use RPC all of the time. So, how do I achieve this function perfectly?
This is the script I use to update the speed variable. Inside the car gameObject I have EntityScript, ControllerScript and other fusion mandatory scripts. EntityScript controls the UI and checks for UI inputs, while ControllerScripts controls the position of the gameObjects.
EnityScript.cs
public override void FixedUpdateNetwork()
{
base.FixedUpdateNetwork();
Debug.Log($"Applied Speed of {Car.name} : {AppliedSpeed}");
transform.position += AppliedSpeed * transform.forward * Runner.DeltaTime;
}
ControllerScript.cs
private void SpeedApplied()
{
if (Object.HasInputAuthority)
{
if (Hud.answer.text == answerValue.ToString())
{
Controller.AppliedSpeed += 10;
Debug.Log($"CheckAnswer AppliedSpeed: {Controller.AppliedSpeed}");
}
else
{
Controller.AppliedSpeed = 15f;
}
}
}
TL;DR
You are changing a
[Networked]
variable locally in the client, as seen in yourObject.HasInputAuthority
checking.[Networked]
variables can only be changed by theStateAuthority
, 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 viaRPCs
from the client to theStateAuthority
.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
For your code, I assume that
StateAuthority
InputAuthority
of the player that controls the carTransform
NetworkObject
NetworkTransform
EntityScript
ControllerScript
InterpolationTarget
of theNetworkObject
AppliedSpeed
is a public[Networked]
variable in theEntityScript
Concept Overview
Only
StateAuthority
can change the network state, including[Networked]
variables. If you have aNetworkTransform
component on theGameObject
, thetransform
of thatGameObject
will then be also part of the network state. Thetransform
of theGameObject
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
orRPC
, you have to ensure that it is theStateAuthority
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 aif (Object.HasInputAuthority)
. This means that you are asking theInputAuthority
to change a[Networked]
variable locally. As mentioned above, onlyStateAuthority
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 onlyStateAuthority
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 useNetworkInput
instead if it is critical to have everything tick-aligned and you would like to use prediction.EntityScript.cs
ControllerScript.cs
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)