Is it possible to have synced NetworkVariables without having them inside a NetworkBehaviour

I have a custom class (lets just say MyClass) that is used throughout my project. It may be in other classes that inherit from NetworkBehaviour but it may not. The problem is, MyClass contains a NetworkVariable to be synced over a Network. I have a method to manually set a NetworkBehaviour on it so that I can have MyClass on any script as long as I reference a NetworkBehaviour. Here is a simple setup:

public class MyMonoBehaviourClass : MonoBehaviour
{
    public NetworkBehaviour MyNetworkBehaviourClass;
    public MyClass MyClassWithNetworkVariable;

    private void Awake()
    {
        MyClassWithNetworkVariable.SetNetworkBehaviour(MyNetworkBehaviourClass);
    }
}
[Serializable]
// I don't know why but the serializer yells at me if I don't add this.
[GenerateSerializationForType(typeof(float))]
public class MyClass
{
    // I have other stuff in this class but simplicity I'm just including the NetworkVariable
    public NetworkVariable<float> MyVariable;

    public void SetNetworkBehaviour(NetworkBehaviour networkBehaviour)
    {
        MyVariable = new NetworkVariable<float>();
        MyVariable.Initialize(networkBehaviour);
        MyVariable.OnValueChanged += OnValueChanged;

        void OnValueChanged(float previousValue, float newValue)
        {
            Debug.Log("New value: " + newValue);
        }
    }
}

I thought by using the NetworkVariable.Initialize() method I could set a NetworkBehaviour to a NetworkVariable from anywhere, but it doesn’t seem to work. I even tried to have it wait to initialize until OnNetworkSpawn() was called. I don’t get any errors and the value properly updates on the host, but nothing happens at all on the client. I doesn’t notice when the value changes on the host or give any errors either.

Is it just not possible to do it this way? Does the MyMonobehaviourClass also need to be a NetworkBehaviour? Any help is appreciated.

I experimented with this for a bit, trying to add netvars to regular C# classes. Alas, this is not possible. Netvars have to be in a NetworkBehaviour component.

Thus (long term)I am considering to eventually ditch the netvars in favor of having a custom storage class (or several) which manage their value synch via custom messages.

The whole concept of embedding RPCs and Netvars in regular logic components is preposterous, and a maintenance nightmare. It‘s akin to having to have GUI method calls littered throughout various components.

At the very least I recommend making custom components per object which contain all that object‘s RPCs and another containing all the NetVars to separate the netcode from everything else.

1 Like

I’m going to mark your comment as the solution because you are correct. There is no way for there to be NetworkVariables in anything but a NetworkBehaviour. They can’t be nested inside a class or put in a list even if those containers are on a NetworkBehaviour. All the forums and other documentation on this seem to point to that conclusion.

I did however find for my specific case that creating my own custom NetworkVariable by inheriting NetworkVariableBase and implementing as shown in the documentation here worked for me. It seems pretty straightforward for most cases. I just dislike how they make certain things which get used in the regular NetworkVariable internal which prevents certain methods/variables from being used in custom ones.

Its also a bit annoying that they only describe why NetworkVariables HAVE to be put in NetworkBehaviour in a tiny little caution block at the very bottom of that documentation link I linked above. At the very least put it at the top to avoid so many similar forum posts and general confusion. It would be really nice if the Unity Editor caught when people try to put NetworkVariables in anything but NetworkBehaviours and warned them in engine because right now it doesn’t give any errors or warning.