When I’m spawning my players and trying to set their health to the initial value, it does not get synced FOR THE SESSION OWNER. Every other player seems to have the correct health. This only happens when using distributed authority. Not sure if I’m doing something wrong or if this is a bug.
My setup basically looks like this:
Player spawner:
IReadOnlyList<ulong> connectedClientIds = NetworkManager.Singleton.ConnectedClientsIds;
for (int i = 0; i < connectedClientIds.Count; i++)
{
NetworkObject playerInstance = Instantiate(playerPrefab);
playerInstance.SpawnWithOwnership(connectedClientIds[i], true);
}
Player health:
private readonly NetworkVariable<int> currentHealthSync = new NetworkVariable<int>();
public override void OnNetworkSpawn()
{
currentHealthSync.OnValueChanged += OnCurrentHealthSynced;
if (HasAuthority)
{
maxHealthSync.Value = startHealth;
currentHealthSync.Value = startHealth;
}
Debug.Log($"Player {OwnerClientId} spawned with health: {currentHealthSync.Value}");
}
private void OnCurrentHealthSynced(int previousValue, int newValue)
{
Debug.Log($"Player {OwnerClientId} health changed from {previousValue} to {newValue}");
}
When spawning, the health for other players is always 0. Not even the synced method gets called. Not even if I put the OnValueChanged subscribe in OnEnable.
I also created a custom editor just to see the current health value, and it’s always 0.
If the value changes at any later point, like taking damage, it does sync properly.
@Hertzole
Hmm… there could be something else happening on your end.
I took your script and created this NetworkBehaviour:
PlayerHealth.cs (869 Bytes)
Added that the player prefab… but I let the NetworkManager handle the spawning.
Let me add a script to manually spawn the players like you are doing to make sure it isn’t a SpawnWithOwnership bug.
@Hertzole
I am not able to replicate the issue. I used this PlayerSpawnHandler.cs (4.1 KB) component.
It has to be attached to the same GameObject your NetworkManager component is attached to and make sure to assign the player prefab to spawn as well as setting the spawn player option:
Using that and the above PlayerHealth NetworkBehaviour I am seeing the correct values being applied when spawned by user script or by NetworkManager.
@NoelStephens_Unity I have been able to replicate the issue in a new project. However, I was not able to reproduce it when I set the player as the player object on the network manager, like you said you did. If I spawn the objects at a later point, the issue occurs.
May I DM you a reproducible project, or should I report a bug instead? I don’t feel comfortable sharing the project publicly due to the service linking.
I recorded a small video showcasing the issue.
Feel free to send me a zip via DM.
You only need to include the Assets, Packages, and ProjectSettings folders.
Note:
When spawning with ownership in a distributed authority network topology it is recommended to spawn from the authority relative instance (i.e. have the client that joins just Spawn the player prefab when it is joined and synchronized) unless you want to have specific control over the spawn process from say the session owner.
The pattern you appear to be using is typically used in a client-server network topology where the server would spawn with ownership as players connect. With distributed authority, you can just let each client spawn their own player prefab.
I would recommend having each client spawn their own player prefab instance upon NetworkSceneManager.OnSynchronizeComplete if you are using the integrated scene management or if you are not then when the newly connected client’s NetworkManager invokes the NetworkManager.OnClientConnected handler the newly connected client would spawn its player prefab instance.
This was verified as a bug and is resolved in PR-3779. This fix should land in the next update.
As a work around, if you are trying to update a NetworkVariable during OnNetworkSpawn when using a distributed authority network topology and the client spawning the NetworkObject is not the targeted owner/authority when creating the NetworkObject using NetworkObject.SpawnWithOwnership, then migrate your script from OnNetworkSpawn to OnNetworkPostSpawn (until the fix is released).
PR-3779 has been merged and will be in the next update. 