Networking Player Movement

Checked with version: 5.3

-

Difficulty: Intermediate

To make the player movement network aware and to make sure that only the local player can control the local player GameObject, we need to update the PlayerController script.

The two biggest changes to the PlayerController script will be to use the namespace UnityEngine.Networking, and to have the PlayerController script derive from NetworkBehaviour rather than MonoBehaviour.

  • Open the PlayerController script for editing.
  • Add the namespace UnityEngine.Networking.
using UnityEngine.Networking;

  • Change MonoBehaviour to NetworkBehaviour.
public class PlayerController : NetworkBehaviour

  • Add a check for isLocalPlayer in the Update function, so that only the local player processes input.
if (!isLocalPlayer)
{
    return;
}

The final script should look like this:

PlayerController

Code snippet

using UnityEngine;
using UnityEngine.Networking;

public class PlayerController : NetworkBehaviour
{
    void Update()
    {
        if (!isLocalPlayer)
        {
            return;
        }

        var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
        var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;

        transform.Rotate(0, x, 0);
        transform.Translate(0, 0, z);
    }
}

The namespace UnityEngine.Networking holds the networking code we will need to write network-aware scripts. For more information on namespaces, please see the page on namespaces in the Manual

The class NetworkBehaviour is a specialized class based on Monobehaviour. Scripts attached to GameObjects that need to use networking features should inherit from NetworkBehaviour. For more information please see the pages on NetworkBehaviour in either the Scripting Reference or the Manual.

Note the check using !isLocalPlayer. LocalPlayer is part of NetworkBehaviour and all scripts that derive from NetworkBehaviour will understand the concept of a LocalPlayer.

What a LocalPlayer is and how it works requires an understanding the architecture of a project using the Multiplayer Networking High Level API (or HLAPI). For more information on the HLAPI please see the page on the HLAPI.

In a networked project, the Server and all of the Clients are executing the same code from the same scripts on the same GameObjects at the same time. This means that in a situation with a Server and two Clients, there will be six potential player GameObjects being processed. This is because there will be two players and therefore two player GameObjects on the Server. There will also be two players on each of the two Clients. This makes a total of six player GameObjects.

description

All of these player GameObjects were spawned from the same player prefab asset and all share a copy of the same PlayerController script. With a script that derives from NetworkBehaviour, which player “owns” what GameObject is understood automatically and is managed as part of the spawning process. The LocalPlayer is the player GameObject “owned” by the local Client. This ownership is set by the NetworkManager when a Client connects to the Server and new player GameObjects are created from the player prefab. When a Client connects to the Server, the instance created on the local client is marked as the LocalPlayer. All of the other player GameObjects that represent this player - whether this is on the Server or another Client - are not marked as a LocalPlayer.

By using the boolean check isLocalPlayer, a script can acknowledge or ignore code depending upon whether or not it is owned by the LocalPlayer. In our case, in Update, we have a check that says:

if (!isLocalPlayer)
{
    return;
}

With this check, only the LocalPlayer can execute the movement code. In the situation with a Server and two Clients, like our example project, the player GameObject on the Server and the remote Client will not be a LocalPlayer. In this case, the code path will return and not execute the movement code. This allows identical scripts on all of the GameObjects that work correctly regardless of whether they are being processed on the Server or any of the game Clients.

If we were to run the example project at this point, the player GameObjects would not stay in sync across all of the instances of the running project. Movement Input would only be processed on the local player GameObject and the position and rotation of that player GameObject would not be updated across the network.

To keep the player GameObjects in sync, we need to add a NetworkTransform component to the player prefab.

  • Save the script.
  • Return to Unity.
  • Select the player prefab asset in the Project Window.
  • With the player prefab asset selected,
  • ... find and add the component: Network > NetworkTransform.
  • Save the Project.

description

This NetworkTransform synchronizes the GameObject’s transform across the network. The local player moves the locally owned player GameObject and only the locally owned player GameObject because of the isLocalPlayer check. The player GameObject's NetworkTransform then synchronizes the position, rotation and scale of the GameObject's transform across the Server and all of the Clients. For more information on the NetworkTransform component, please see the page on the NetworkTransform.

Related documentation