Search Issue Tracker

Won't Fix

Votes

0

Found in [Package]

1.0.0

Issue ID

NCCBUG-178

Regression

No

NetworkVariable with both Read&Write Permission set to Owner doesn't have its Value updated to Server

Package: Multiplayer Netcode for GameObjects

-

Based on [GitHub issue 2094|https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/issues/2094]

h2. Description
Network Variable with both ReadPerm = NetworkVariableReadPermission.Owner and WritePerm = NetworkVariableWritePermission.Owner doesn't have the value updated from Owner Client to Server.

h2. Reproduction Steps

# Declare a NetworkVariable of any type T with both Read & Write Permission set to Owner. (i.e. new NetworkVariable(default, NetworkVariableReadPermission.Owner, NetworkVariableWritePermission.Owner)
# Have two instance of game running, one join as Host, another one join as Client.
# Attempt to update the NetworkVariable on the Owner Client.
# Print out the resulting NetworkVariable Value on Server.

h2. Actual Outcome
The Value of NetworkVariable has been updated on the Owner Client side, but on the Server side, it remains the default value.

h2. Expected Outcome
The Value of NetworkVariable on the Server side should be synced to the Value of Owner Client side, according to netcode documents (https://docs-multiplayer.unity3d.com/netcode/current/basics/networkvariable/index.html) as well as the comment inside "NetworkVariableReadPermission.cs" (Line 13: /// Only the owner and the server can read).

h2. Additional Technical Notes
This was verified by using the following script and manually testing:
{code:java}
using System.Collections;
using UnityEngine;
using Unity.Netcode;

namespace TestProject.ManualTests
{
public class OwnerNetworkVariableTest : NetworkBehaviour
{
private NetworkVariable<int> m_OwnerTest = new NetworkVariable<int>(0, NetworkVariableReadPermission.Owner, NetworkVariableWritePermission.Owner);

public override void OnNetworkSpawn()
{
if (IsOwner && !IsServer)
{
StartCoroutine(OwnerUpdateValue());
}
else if (IsServer)
{
m_OwnerTest.OnValueChanged += OnOwnerTestChanged;
}
base.OnNetworkSpawn();
}

public override void OnNetworkDespawn()
{
if (IsOwner && !IsServer)
{
StopCoroutine(OwnerUpdateValue());
}
else if (IsServer)
{
m_OwnerTest.OnValueChanged -= OnOwnerTestChanged;
}
base.OnNetworkDespawn();
}

private void OnOwnerTestChanged(int previous, int current)
{
Debug.Log($"[Server] Detected Owner({OwnerClientId}) updated value to: {current}");
}

private IEnumerator OwnerUpdateValue()
{
var waitUntil = new WaitForSeconds(0.1f);
while (m_OwnerTest.Value < 100)
{
m_OwnerTest.Value += 1;
yield return waitUntil;
}
}
}
}
{code}

h2. The issue:
NetworkVariableBase.cs:
The original code only checked if the target id could read:

{code:java}
public bool CanClientRead(ulong clientId)
{
switch (ReadPerm)
{
default:
case NetworkVariableReadPermission.Everyone:
return true;
case NetworkVariableReadPermission.Owner:
return clientId == m_NetworkBehaviour.NetworkObject.OwnerClientId;
}
}
{code}
This would always return false under the condition of "owner,owner" for the server.

*The fix:*

{code:java}
public bool CanClientRead(ulong clientId)
{
switch (ReadPerm)
{
default:
case NetworkVariableReadPermission.Everyone:
return true;
case NetworkVariableReadPermission.Owner:
return clientId == m_NetworkBehaviour.NetworkObject.OwnerClientId || NetworkManager.ServerClientId == clientId;
}
}
{code}
The above checks if the target is the owner or if the target is the server.

Still need to make sure that this doesn't impact anything else, but so far it fixes the issue.

NetworkVariableDeltaMessage.Serialize also needed to have its logic updated as it could happen there too.

  1. Resolution Note:

Add comment

Log in to post comment

All about bugs

View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.