Description
Description
leaving original title and description for context.
NetworkShow does not set NetworkVariables
When we call NetworkHide on a dynamically created object, and later call NetworkShow, the object's network variables are not set.
NetworkHide will despawn and destroy the object on the client, so when the server calls NetworkShow, we are now creating a new object on the client, except this time the network variables don't get set.
Upon further testing, the issue turned out to be that NetworkVariable.OnValueChanged is not being called on the client, UNLESS the value changed while the network object existed on the client.
So if the client connects, and the network variable already had its value set on the server, OnValueChanged will not get called on the client.
Similarly, if the object is network hidden on the client side, when it becomes shown again, OnValueChanged is not called for the network variable; for a dynamically created network object it also gets destroyed on the client, not just network hidden.
Not sure if the parent hierarchy is playing a role here, but my network object is a child of another network object.
For the test, I have a Canvas that's an in-scene network object, then I dynamically (at run time) add a network object child to it (on the server), this network object has the behavior below, then I spawn this network object.
public class TestBehaviour : NetworkBehaviour
{
NetworkVariable<float> _networkVariable;
[SerializeField]
private TMP_Text _text;
private void Awake()
{
_networkVariable = new NetworkVariable<float>();
_networkVariable.OnValueChanged += OnNetworkVariableChanged;
}
private void OnNetworkVariableChanged(float previousValue, float newValue)
{
text.text = _networkVariable.Value.ToString();
}
private void Update()
{
if (_networkVariable != null)
{
_text.text = _networkVariable.Value.ToString();
}
}
public override async void OnNetworkSpawn()
{
if (!NetworkManager.Singleton.IsServer)
{
return;
}
await new WaitForSeconds(10); // give time for client to connect.
_networkVariable.Value = 69; // by now client connected, the client will have OnNetworkVariableChanged raised here.
await new WaitForSeconds(10);
NetworkObject.NetworkHide(1);
_networkVariable.Value = 12; // here we change the value while the object is hidden for the client
await new WaitForSeconds(10);
NetworkObject.NetworkShow(1); // here we show the object to the client, since this object is dynamically created, a new instance will be created, BUT OnNetworkVariableChanged is never raised.
}
}
While inspecting this scene on the client side in the editor, I see everything behaving properly except for that OnNetworkVariableChanged method, it does not get raised unless a change took place while the network object existed.
This issue was not present in Netcode v1.0.0, I started experiencing it in v1.1.0
Actual Outcome
NetworkVariable.OnValueChanged is not called on the client unless the change took place while the object existed on the client.
Expected Outcome
NetworkVariable.OnValueChanged should be called when the variable's value changes, regardless if the change took place while the object existed on the client or not.
Environment
- OS: Win10
- Unity Version: 2022.1.23f1
- Netcode Version: 1.1.0