Skip to content

Unity Networking

GhostProtocolMatrix edited this page Mar 9, 2018 · 13 revisions

These are some observations about the Unity Networking API.

Calling functions somewhere else

  • Call a function on the server from a client: [Command]
  • Call a function on all clients from the server: [ClientRPC]
  • Call a function on a specific client from the server: [TargetRPC]

Adding a command as an event handler (someObject.OnEvent += CmdHandler;) does not work. The function is run on the client instead of the server without any type of message or error.

[Command] methods can only be called on objects that are localPlayer or have local authority.

Unsurprisingly, [ClientRPC]/[TargetRPC] methods can only be called on the server.

Synchronizing values across all computers [SyncVar]

[SyncVar] will only sync changes if the variable is changed on the server. This has no regard for localPlayer or localAuthority. Even if it is on an attribute of a class on a gameObject with a network identity component marked as having local authority, it will still not sync changes that are made by the client.

Because of this, [SyncVar] will normally be pared with a [Command] method so that its value can be changed.

Attempting to set a [SyncVar] on the client fails silently. (Which is dumb.)

You can add a function to be called when the SyncVar updates like this [SyncVar (hook = "functionToCall")]. This function will only be called on the client. If you do this you must set the variable's new value in functionToCall. Adding a hook to a SyncVar causes unity to no longer update the value automatically.

Local Player and Authority

From what I can gather, Unity originally only supported a single GameObject having local authority on the client. That is, only one GameObject in the entire game could call [Command] methods and otherwise manage itself. This was fixed when they introduced the concept of local authority. Now objects that are marked as having local authority can do all those fun localPlayer things like calling [Command] methods. Unfortunately, they did not merge the localPlayer concept into the new local authority, so now we have two nearly identical but subtly different ways to do essentially the same thing. Some observations:

  • When a network connection is lost (the player closes the game, etc.) all objects marked as the localPlayer or as having local authority that were associated with that connection are automagically destroyed.
  • Only a single object can be localPlayer, but any number of objects can be local authority.
  • Spawn an object under the server's control with NetworkServer.Spawn()
  • Spawn an object under a player's control with NetworkServer.SpawnWithClientAuthority()
  • Spawn an object as the localPlayer object with NetworkServer.AddPlayerForConnection()
  • this.connectionToClientis used on the server to get the connection to the client. This only works for objects that are the local player.
  • Meanwhile, this.clientAuthorityOwner is used on the server to get the connection to the client. This property only works for objects that have local authority.
  • The local player has a startup method that can be overridden: OnStartLocalPlayer
  • Objects with local authority also have a startup method that can be overridden: OnStartAuthority. This method is called on the localPlayer object as well.
  • Those methods appear to be identical, except for the obvious difference between one being for local player and the other for local authority.
  • Local authority objects also have a method called OnStopAuthority that will be called if local authority is removed from them with NetworkIdentity.RemoveClientAuthority.
  • Local authority can be assigned with NetworkIdentity.AssignClientAuthority, and removed with NetworkIdentity.RemoveClientAuthority. These functions probably only work on the server. I don't know what would happen if you tried them on the client, but given Unity's track record they would probably fail silently.

Method Dichotomy

Most functions have a specific place they are intended to be called. (i.e. Either the server or the client.) While Unity could have designed the API in a way that made calling client functions on the server a compile time error, instead the made it a run-time error. Worse, they made it an opt-in run-time error. Because of this, you should mark all of your methods with [Server] and [Client]. I even find it helpful to mark lifetime methods with them such as OnStartClient and OnStartAuthority, just to get a message earlier in the debug process if something isn't working as expected.

Methods marked with [Server] that are called on the client will not run, and will trigger a warning in the debug console. Methods marked with [Client], similarly, will not run if called on the server and will trigger a warning in the debug console.

Network Management

Objects inheriting the NetworkManager class can not use [Server], [Client], [Command], [ClientRPC], or [TargetRPC]. (i.e., any of the super useful attributes that would be really nice to use.)

Clone this wiki locally