Skip to main content

Golden Path Module One

In this guide we cover the following:

  • Adding scripts to your objects
  • Adding editor modes inside your game (Host, Server, and Client)
  • Basic Player Movement
  • Basic RPC use

Prerequisites#

You should have completed the Golden Path Foundation module before starting this tutorial. We use the Foundation module as the base for this and other Golden Path modules.

Create a Clone 'GoldenPath' project#

important

Cloning your Foundation GoldenPath project does not support rollback, so it will only work on the Unity version that it was originally created for. Attempting to open the clone on a newer or older version of Unity may cause unexpected funcationality.

We create a clone of the Golden Path Foundation project for further Golden Path modules, if you have not yet created a GoldenPath project then you should follow the steps here to create one. Working from a clone of the initial project will help you learn about new features and concepts without having to repeat previous work.

Create a clone of GoldenPath#

  1. Navigate to where your Golden Path project is stored.

    note

    For the video guide we used a Mac and our path was ~/dev/mlapi-golden-path/. On a Windows machine your path may be slightly different. As one of our writer's stepped through the process in both Mac and Windows, these are her comparative paths:

    • Mac: ~ GoldenPath
    • Windows: C:\Users\sarao\GoldenPath :::
  2. Create a new folder and name it Golden Path_<modulenumber>.

    tip

    For the purposes of the Golden Path series, I will replace modulenumber with the current module number of the series. You do not have to, though, you may find it makes following the series easier.

    Our comparative paths of the new folder for module one:

    • Mac in video: ~/dev/mlapi-golden-path/Golden_Path_One
    • Mac: ~GoldenPath_One
    • Windows: C:\Users\sarao\GoldenPath_One
  3. Open your GoldenPath folder from the Foundation module, select all the content within to Copy, then Paste into your new Golden Path_<modulenumber> folder.

From the Video

I moved my new folder to keep my file structure clean its not a required step, but it does look nice.

Add the clone to Unity Hub#

To add your clone project in Unity Hub version 3.0.0+: 1. Open Unity Hub. 1. From the dropdown arrow between **Open** and **New project**, click **Add project from disk**. 1. Navigate to where the clone folder is saved, select `GoldenPath_<modulenumber>`, and click **Open**/**Select Folder**.

The clone project should now appear in your projects list of the Unity Hub as GoldenPath_&lt;modulenumber&gt;.

To add your clone project in previous Unity Hub versions: 1. Open Unity Hub. 2. Click **Add**. 3. Navigate to where the clone folder is saved, select `GoldenPath_<modulenumber>`, and click **Open**/**Select Folder**.

The clone project should now appear in your projects list of the Unity Hub as GoldenPath_&lt;modulenumber&gt;.

Open GoldenPath_One#

  1. Open Unity Hub.
  2. Select GoldenPath_One from the list of projects displayed.

Adding Scripts to GoldenPath#

This section will add some scripts to Golden Path similar to part two of the Hello World guide that contain the new features we will be covering in this module.

  1. In the Hierarchy menu, right-click and select Create Empty to create an empty GameObject that you should name HelloWorldManager.

  2. Right-click on the Scripts folder under Project tab > Assets, and Create a new C# Script. Name this script HelloWorldManager.

  3. Add the HelloWorldManager script as a component to your recently created HelloWorldManager GameObject. To do this, select the HelloWorldManager GameObject, click Add Component under the Inspector tab, and select Scripts > HelloWorldManager.

  4. Open the HelloWorldManager.cs script in a text editor of your choice to edit it to match the following code block.

How to Copy

We recommend that you use the Copy function in our code blocks to reduce errors when copying and pasting content. Hover over the block and select the Copy button that appears in the upper-right corner of the code block. Then paste the content as needed.

Click to show/hide the Code.
using Unity.Netcode;
using UnityEngine;
namespace HelloWorld
{
public class HelloWorldManager : MonoBehaviour
{
void OnGUI()
{
GUILayout.BeginArea(new Rect(10, 10, 300, 300));
if (!NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsServer)
{
StartButtons();
}
else
{
StatusLabels();
SubmitNewPosition();
}
GUILayout.EndArea();
}
static void StartButtons()
{
if (GUILayout.Button("Host")) NetworkManager.Singleton.StartHost();
if (GUILayout.Button("Client")) NetworkManager.Singleton.StartClient();
if (GUILayout.Button("Server")) NetworkManager.Singleton.StartServer();
}
static void StatusLabels()
{
var mode = NetworkManager.Singleton.IsHost ?
"Host" : NetworkManager.Singleton.IsServer ? "Server" : "Client";
GUILayout.Label("Transport: " +
NetworkManager.Singleton.NetworkConfig.NetworkTransport.GetType().Name);
GUILayout.Label("Mode: " + mode);
}
static void SubmitNewPosition()
{
if (GUILayout.Button(NetworkManager.Singleton.IsServer ? "Move" : "Request Position Change"))
{
var playerObject = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
var player = playerObject.GetComponent<HelloWorldPlayer>();
player.Move();
}
}
}
}
  1. Save your code in your text editor and return to Unity. Unity may take a moment to compile your changes.
    note

    You may see an error about HelloWorldPlayer not being found. This is okay; we will be addressing this error in a later section.

Editor Modes to Golden Path (The HelloWorldManager Script)#

Inside the HelloWorldManager.cs script, we define two methods that mimic the editor buttons inside of the NetworkManager during Play mode.

Click to show/hide the Code.
static void StartButtons()
{
if (GUILayout.Button("Host")) NetworkManager.Singleton.StartHost();
if (GUILayout.Button("Client")) NetworkManager.Singleton.StartClient();
if (GUILayout.Button("Server")) NetworkManager.Singleton.StartServer();
}
static void StatusLabels()
{
var mode = NetworkManager.Singleton.IsHost ?
"Host" : NetworkManager.Singleton.IsServer ? "Server" : "Client";
GUILayout.Label("Transport: " +
NetworkManager.Singleton.NetworkConfig.NetworkTransport.GetType().Name);
GUILayout.Label("Mode: " + mode);
}

NetworkManager implements the singleton pattern as it declares Singleton. This is defined when the MonoBehaviour is enabled.

This component also contains very useful properties:

  • IsClient - For whether or not a client is running
  • IsServer - For whether or not a server is running
  • IsLocalClient - For whether the server calls a local client or not

IsClient and IsServer are already established to dictate the connection state.

We call these methods inside OnGUI().

Click to show/hide the Code.
void OnGUI()
{
GUILayout.BeginArea(new Rect(10, 10, 300, 300));
if (!NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsServer)
{
StartButtons();
}
else
{
StatusLabels();
SubmitNewPosition();
}
GUILayout.EndArea();
}
note

You will notice the introduction of a new method, SubmitNewPosition(), which we will be using later.

Adding basic movement to the Player object#

  1. Under your Project tab, right-click on your Scripts folder. Hover over Create and select C# Script that you rename HelloWorldPlayer.
  2. Right-click and Open or double-click the HelloWorldPlayer.cs script from your Scripts folder in the Project tab. It will open in your text editor.
  3. Copy and paste the following code block into your HelloWorldPlayer.cs script, overwriting the autogenerated content. Save your changes. The error you may have seen from updating HelloWorldManger.cs should be resolved now.
    How to Copy

    We recommend that you use the Copy function in our code blocks to reduce errors when copying and pasting content. Hover over the block and select the Copy button that appears in the upper-right corner of the code block. Then paste the content as needed.

Click to show/hide the Code.
using Unity.Netcode;
using UnityEngine;
namespace HelloWorld
{
public class HelloWorldPlayer : NetworkBehaviour
{
public NetworkVariable<Vector3> Position = new NetworkVariable<Vector3>();
public override void OnNetworkSpawn()
{
Move();
}
public void Move()
{
if (NetworkManager.Singleton.IsServer)
{
var randomPosition = GetRandomPositionOnPlane();
transform.position = randomPosition;
Position.Value = randomPosition;
}
else
{
SubmitPositionRequestServerRpc();
}
}
[ServerRpc]
void SubmitPositionRequestServerRpc(ServerRpcParams rpcParams = default)
{
Position.Value = GetRandomPositionOnPlane();
}
static Vector3 GetRandomPositionOnPlane()
{
return new Vector3(Random.Range(-3f, 3f), 1f, Random.Range(-3f, 3f));
}
void Update()
{
transform.position = Position.Value;
}
}
}
  1. Select the Player prefab from Project tab > Assets > Prefabs.
  2. From the Inspector tab, scroll to the bottom to click on Add Component. Select Scripts > HelloWorld > HelloWorldPlayer to add the script as a component.

This class inherits from NetworkBehaviour instead of MonoBehaviour.

Click to show/hide the Code.
public class HelloWorldPlayer : NetworkBehaviour

Inside this class, we now define a NetworkVariable to represent this player's networked position.

Click to show/hide the Code.
public NetworkVariable<Vector3> Position = new NetworkVariable<Vector3>();

HelloWorldPlayer overrides OnNetworkSpawn.

Click to show/hide the Code.
public override void OnNetworkSpawn()
{
Move();
}

Any MonoBehaviour implementing NetworkBehaviour can override the Netcode for GameObjects method OnNetworkSpawn(). This method is fired when the NetworkObject gets spawned and the networking is setup. We override OnNetworkSpawn since a client and a server will run different logic here.

note

This can be overriden on any NetworkBehaviour.

On both client and server instances of this player, we call the Move() method to do the following:

Click to show/hide the Code.
public void Move()
{
if (NetworkManager.Singleton.IsServer)
{
var randomPosition = GetRandomPositionOnPlane();
transform.position = randomPosition;
Position.Value = randomPosition;
}
else
{
SubmitPositionRequestServerRpc();
}
}

Some simple RPC use#

If this player is a server-owned player, at OnNetworkSpawn() we can immediately move this player, as suggested in the following code.

Click to show/hide the Code.
if (NetworkManager.Singleton.IsServer)
{
var randomPosition = GetRandomPositionOnPlane();
transform.position = randomPosition;
Position.Value = randomPosition;
}

If we are a client, we call a ServerRpc. A ServerRpc can be invoked by a client to be executed on the server.

Click to show/hide the Code.
else
{
SubmitPositionRequestServerRpc();
}

This ServerRpc simply sets the position NetworkVariable on the server's instance of this player by just picking a random point on the plane.

Click to show/hide the Code.
[ServerRpc]
void SubmitPositionRequestServerRpc(ServerRpcParams rpcParams = default)
{
Position.Value = GetRandomPositionOnPlane();
}

The server instance of this player has just modified the Position NetworkVariable. This means that if we are a client, we need to apply this position locally inside of our Update loop.

Click to show/hide the Code.
void Update()
{
transform.position = Position.Value;
}

We can now go back to HelloWorldManager.cs and define the contents of SubmitNewPosition(). The following code is already saved in your script if you copied and pasted the HelloWorldManager codeblock in the previous section.

Click to show/hide the Code.
static void SubmitNewPosition()
{
if (GUILayout.Button(NetworkManager.Singleton.IsServer ? "Move" : "Request Position Change"))
{
var playerObject = NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject();
var player = playerObject.GetComponent<HelloWorldPlayer>();
player.Move();
}
}

Whenever you press the GUI button (which is contextual depending on if you are server or a client), you find your local player and simply call Move().

You can now create a build that will demonstrate the concepts outlined above. We are going to create two build instances so you can see players move around each other in your Hello World game.

tip

Make sure SampleScene is included in BuildSettings.

  1. Go to File > Build Settings and select Add Open Scenes. This should add Scenes/SampleScene to Scenes In Build.
  2. Select Build And Run and save this first instance as HelloWorld.
  3. Select Build And Run again, but save this second instance as HelloWorld2.
  4. Select one of your build instances as Host mode and the other as Client mode.
  5. Click the Move/Request Position Change in your instances to watch your players move around each other. As you press the GUI button, the server will move immediately and be replicated on client. Client can request a new position, which will instruct the server to modify that server instance's position NetworkVariable. That client will apply that NetworkVariable position inside of it's Update() method.
Congrats!

Congratulations you have learned the basics of a networked game!

Next Steps#

For more information on the relevant concepts introduced here please refer to the following sections of the documentation:

Special Thanks

This guide would not have been possible without the hard work and support of Fernando Cortez, Unity.