Open lllando opened 3 days ago
@lllando You cannot use static NetworkVariables on any platform as each NetworkVariable needs to know what NetworkObject and NetworkBehaviour instance the property belongs to in order to properly be synchronized between clients.
If you want to use NetworkVariables to store a global state, then I would recommend a separate in-scene placed NetworkObject.
@NoelStephensUnity Ok good to know, thanks - like you said it is easy to work around. Interesting that I only ran into the error when switching away from Mono though.
Could you shed some more light as to why a NetworkVariable would need to know which instance the property belongs to even in the case of static variables? My understanding is that by definition any instance could be used as the information held by the static NetworkVariable would be the same across all instances.
@lllando I would be happy to shed some light on why static NetworkVariables shouldn't be used and why they should cause issues if you try to use them. In order to fully understand this I have to sort of walk through how GameObjects are identified and synchronized.
A NetworkObject
component added to a GameObject
provides the ability for the object instance to be replicated across clients. This is accomplished by spawning the NetworkObject
. When a NetworkObjet
is spawned, it is assigned a NetworkObjectId
and is owned by one of the clients or the host/server.
With the client-server network topology, the host/server controls the spawning, ownership, and despawning of the NetworkObject
. This means the network prefab (at minimum a GameObject
with a NetworkObject
component) is instantiated first on the server/host side and then spawned. Once spawned, a CreateObjectMessage is sent to all of the clients who then create a clone instance and spawn that clone instance locally where the serialized properties of the NetworkObject
and any NetworkBehaviour
components are applied.
With the distributed authority network topology, the owner controls the spawning, and despawning of the NetworkObject
. Control over ownership is defined by the ownership flags. This means the network prefab is instantiated first on the owning client side and then spawned. Once spawned, a CreateObjectMessage is sent to all of the clients who then create a clone instance and spawn that clone instance locally where the serialized properties of the NetworkObject
and any NetworkBehaviour
components are applied.
NetworkBehaviour
components are associated with a specific NetworkObject
instance and each NetworkBehaviour
component is assigned a NetworkBehaviourId
. When a message is sent between instances, the NetworkObjectId
and NetworkBehaviourId
are used to route the message to the correct NetworkObject
and NetworkBehaviour
instances.
NetworkVariable
properties are defined at a NetworkBehaviour
scope. This means that if a NetworkVariable
property changes then to deliver the NetworkVariableDeltaMessage
to other clients it uses the NetworkObjectId
, NetworkBehaviourId
, and and internally tracked NetworkVariable identifier.
NetworkObjectId-->NetworkBehaviourId-->NetworkVariable Identifier--> apply delta state
So, if you have a NetworkVariable
defined in a NetworkBehaviour
that is say...on a player... then when that NetworkVariable is updated it updates on all instances of that specific player. Since it is common to have the same network player prefab used to create player instances for all clients connected to a session, each client would have a unique instance cloned/replicated on each client (and server or host if using client-server). This means that any changes to a NetworkVariable
of a client's player instance will be replicated across all clients (and server or host if using client-server) to reflect the change in the value of the NetworkVariable
.
Since NetworkVariable
properties have read/write permission settings and those settings can be specific to an owner, if you have a NetworkVaraible
that is set to owner write permissions then if that NetworkVariable
property was static player (using the scenario before) could make changes to the NetworkVariable
but which instance would be updated and what happens if multiple clients change the static NetworkVariable
at the same time (i.e. a race condition would occur). Then there is the issue of registering with events...using the player prefab scenario if you wanted a client to receive notifications when a static NetworkVariable
changed and say you subscribed within the OnNetworkSpawn method. then you would end up registering multiple times for the same NetworkVariable
property instance (since it is static) and would receive multiple event notifications for a single change in the value (roughly one for each client).
However, you do bring up a good point and we should have some form of notification or block during compilation that provides you with a message about this and it does appear that it will allow you to use it (which it shouldn't) under other platforms (Windows, OSX, etc.).... which it shouldn't do that.
I will track this issue with our QA (@fluong6 ) and see if we can get some better documentation first and then possibly detect this use case and just not allow it.
Description
Build error when compiling using IL2CPP for Android if project uses static NetworkVariables. This behaviour happens when attempting to build using IL2CPP scripting backend and building to Android. Building to Android using Mono builds successfully with no errors, leading me to believe this is a bug/unintended.
Reproduce Steps
public static NetworkVariable<int>
in my case)Actual Outcome
Build fails with two error messages in console.
Expected Outcome
Build should compile successfully with no errors.
Screenshots
Error in Console:
Environment
Additional Context
Full Error Logs: