Skip to content
This repository was archived by the owner on Jul 23, 2025. It is now read-only.

fix: tutorial improvements #840

Merged
merged 14 commits into from
Nov 10, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/tutorials/goldenpath_series/gp_intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ Next steps will likely involve the existing Golden Path series to be completely

|<div class="buttons-pages">Hello World</div>| <div class="buttons-pages">Golden Path One</div>|
| --- | --- |
| Creating a new project<br/> Installing Netcode<br/> Creating and testing the basic networking building blocks<br/> | Adding scripts to objects<br/> Editor modes (Host Server and Client)<br/> Basic player movement <br/>Basic RPC and Network variable use |
| [Creating a new project](../helloworld.md#create-a-new-project-in-unity)<br/> [Installing Netcode](../helloworld.md#install-netcode)<br/> [Creating and testing the basic networking building blocks](../helloworld.md#create-the-basic-components)<br/> | [Editor modes (Host Server and Client)](gp_module_one.md#adding-editor-modes-to-hello-world)<br/> [Basic player movement](gp_module_one.md#adding-basic-movement-to-the-player-object) <br/>[Basic RPC and Network variable use](gp_module_one.md#some-simple-rpc-use) |
</div>
<div class="table-columns-plain">

| <div class="buttons-pages">Golden Path Two</div>|
| --- |
| Network variables (server-controlled)<br/> Network transforms <br/> More on RPCs|
| [Network variables (server-controlled)](gp_module_two.md#introducing-a-server-controlled-network-variable)<br/> [Network transforms](gp_module_two.md#introducing-network-transform) <br/> [More on RPCs](gp_module_two.md#introducing-rpcs)|


</div>
152 changes: 69 additions & 83 deletions docs/tutorials/goldenpath_series/gp_module_one.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,79 +27,15 @@ You should have completed the [Hello World project](../helloworld.md) before sta
1. Open Unity Hub.
1. Select `Hello World` from the list of projects displayed.

## Adding Scripts to Hello World

This section adds some scripts to Hello World that contain the new features covered in the tutorial.
1. Click the **Assets** folder.
2. Open the **Scripts** folder.

### Adding the `HelloWorldPlayer.cs` script

1. Create a new script `HelloWorldPlayer`.
1. Open the `HelloWorldPlayer.cs` script.
1. Edit the `HelloWorldPlayer.cs` script to match the following.

<details open>
<summary>Click to show/hide the Code.</summary>

```csharp
using Unity.Netcode;
using UnityEngine;

namespace HelloWorld
{
public class HelloWorldPlayer : NetworkBehaviour
{
public NetworkVariable<Vector3> Position = new NetworkVariable<Vector3>();

public override void OnNetworkSpawn()
{
if (IsOwner)
{
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;
}
}
}
```
</details>
## Adding Editor Modes to Hello World

### Adding the `HelloWorldManager.cs` script
In the HelloWorld project, you created a **NetworkManager** by adding the pre-created **NetworkManager** component. In Play Mode, the NetworkManager shows Editor buttons labeled `Start Host`, `Start Client`, and `Start Server` in its inspector. These call the `StartHost`, `StartClient` and `StartServer` methods of the **NetworkManager** respectively, to initiate a networking session. Inside the `HelloWorldManager.cs` script, we define two methods which mimic this functionality via UI buttons and status labels.

1. Create an empty `GameObject` rename it **HelloWorldManager**.
1. Create a script called `HelloWorldManager`.
1. Open the `HelloWorldManager.cs` script.
1. Edit the `HelloWorldManager.cs` script to match the following.
2. Open the **Scripts** Folder.
3. Create a script called `HelloWorldManager`.
4. Open the `HelloWorldManager.cs` script.
5. Edit the `HelloWorldManager.cs` script to match the following.

:::tip
You can copy the script from here and paste it into your file.
Expand Down Expand Up @@ -180,10 +116,6 @@ namespace HelloWorld

1. Add the `HelloWorldManager` script component to the `HelloWorldManager` `GameObject`.

## Adding Editor Modes to Hello World

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

<details open>
<summary>Click to show/hide the Code.
</summary>
Expand All @@ -208,7 +140,7 @@ Inside the `HelloWorldManager.cs` script, we define two methods which mimic the
```
</details>

`NetworkManager` implements the singleton pattern as it declares its singleton named `Singleton`. This is defined when the `MonoBehaviour` is enabled. This component also contains very useful properties, such as `IsClient`, `IsServer`, and `IsLocalClient`. The first two dictate the connection state we have currently established that you will use shortly.
The `NetworkManager` instance can be accessed statically from any other scripts via its singleton named `Singleton`. This is defined when the `MonoBehaviour` is enabled. This component also contains very useful properties, such as `IsClient`, `IsServer`, and `IsLocalClient`. The first two dictate the connection state we have currently established that you will use shortly.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can statically access the NetworkManager instance from any other scripts via its singleton named Singleton. This is defined when the MonoBehaviour is enabled. This component also contains very useful properties, such as IsClient, IsServer, and IsLocalClient. The IsClient and IsServer properties dictate the connection state we have currently established that you will use shortly.

How does this sound?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

much better


We call these methods inside of `OnGUI()`.

Expand Down Expand Up @@ -244,7 +176,67 @@ You will notice the introduction of a new method, `SubmitNewPosition()`. This is

## Adding basic movement to the Player object

The `HelloWorldPlayer.cs` script adds some basic movement to the Hello World player.
Here we will create a `HelloWorldPlayer.cs` script that adds some basic movement to the Hello World player.

1. Open the **Scripts** Folder.
1. Create a new script called `HelloWorldPlayer`.
1. Open the `HelloWorldPlayer.cs` script.
1. Edit the `HelloWorldPlayer.cs` script to match the following.

<details open>
<summary>Click to show/hide the Code.</summary>

```csharp
using Unity.Netcode;
using UnityEngine;

namespace HelloWorld
{
public class HelloWorldPlayer : NetworkBehaviour
{
public NetworkVariable<Vector3> Position = new NetworkVariable<Vector3>();

public override void OnNetworkSpawn()
{
if (IsOwner)
{
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;
}
}
}
```
</details>


1. Select the **Player** prefab.
Expand Down Expand Up @@ -306,13 +298,7 @@ https://github.com/Unity-Technologies/com.unity.multiplayer.samples.poc/tree/fea
```
</details>

Any `MonoBehaviour` implementing `NetworkBehaviour` can override the Netcode method `OnNetworkSpawn()`. This method is fired when the `NetworkObject` gets spawned. 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, which will simply do the following.
In a networked game, server/host machines may need to run different functions to a networked player/client. (For example, in a server-authoritative game, the client would handle the player inputs but the movement would be done on the server). All of the instances of this script in the game, whether they're the host/server or a client, will call the `OnNetworkSpawn` method when the `NetworkObject` to which this script is attached has spawned, but only its owner will call the `Move` method. In the case of a Player Object, every client (or host) will have one instance spawned for them, for which they will be the owner. Calling this in `OnNetworkSpawn` makes sure that the NetworkObject has finished spawning so the check to see whether the player is a Server/Host or Client is valid. The `Move` method can then implement different logic depending on the answer (so that Servers do one thing, and Clients do another).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a networked game, the dedicated server (or host) might need to run different functions than the networked player (the client). For example, in a server-authoritative game, the client would handle the player inputs, but the server would handle the movement. All instances of this script in the game, whether running on a server/host or a client, call the OnNetworkSpawn method when the NetworkObject to which this script is attached has spawned, but only its owner will call the Move method. In the case of a Player Object, every client (or host) has an instance of this script spawned for them, for which they are the owner. Calling this in OnNetworkSpawn ensures that the NetworkObject has finished spawning, so the check to see whether the player is a server/host or client is valid. The Move method can then implement different logic depending on the answer (so that servers do one thing, and clients do another).

I took a shot at rewording this paragraph a bit, but some things still aren't clear to me:

In the case of a Player Object, every client (or host) has an instance of this script spawned for them, for which they are the owner.

I want to convert this to active voice, but I'm unsure what spawns the script instance.

Calling this in OnNetworkSpawn ensures ...

It's not clear what "this" refers to here. Is it referring to the Move method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to convert this to active voice, but I'm unsure what spawns the script instance.

The Player Object (which is a GameObject with a NetworkObject component, and in this case also the script this section is talking about) is spawned by Netcode directly. Maybe we should also add a link to this doc? https://docs-multiplayer.unity3d.com/netcode/current/basics/networkobject#player-objects

It's not clear what "this" refers to here. Is it referring to the Move method?

Yes

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, how does this sound? :D

In a networked game, the dedicated server (or host) might need to run different functions than the networked player (the client). For example, in a server-authoritative game, the client would handle the player inputs, but the server would handle the movement. All instances of this script in the game, whether running on a server/host or a client, call the OnNetworkSpawn method when the NetworkObject to which this script is attached has spawned, but only its owner will call the Move method. In the case of a Player Object, Netcode spawns an instance of this script for every client and host (for which they are the owner). Calling the Move method in OnNetworkSpawn ensures that the NetworkObject has finished spawning, so the check to see whether the player is a server/host or client is valid. The Move method can then implement different logic depending on the answer (so that servers do one thing, and clients do another).

I'm also on board with linking to the player objects documentation. I'm not entirely sure if the relative URL I used here is correct, though 😅

Copy link
Contributor Author

@LPLafontaineB LPLafontaineB Nov 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good! I also added a few words to clarify that Netcode spawns the player objects, which then contain the scripts, and a bit more context to the use of OnNetworkSpawn


<details open>
<summary>Click to show/hide the Code.
Expand Down
4 changes: 2 additions & 2 deletions docs/tutorials/goldenpath_series/gp_module_two.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ Now we check that the Network Transform functions correctly.

1. Select **File** > **Build and Run**.
1. Stop the player.
1. Launch the client and server together in a terminal as shown in [Testing the command line helper](#testing-the-command-line-helper).
1. Launch the client and server together in a terminal as shown in [Testing the command line helper](../helloworld.md#testing-the-command-line-helper).
1. After a brief delay, the client and server will spawn.
1. You should see the player capsule moving in a circle on both the client and the server.

Expand Down Expand Up @@ -212,7 +212,7 @@ Now we will test that the client and server are both recieving the RPCs correctl

1. Select **File** > **Build and Run**.
1. Stop the player.
1. Launch the client and server together in a terminal as shown in [Testing the command line helper](#testing-the-command-line-helper).
1. Launch the client and server together in a terminal as shown in [Testing the command line helper](../helloworld.md#testing-the-command-line-helper).
1. After a brief delay, the client and server will spawn.
1. In the console, you should expect to see the client and server sending RPC messages to each other.
1. The client kicks off the exchange in its `Update` call the first time with a counter value of 0.
Expand Down
13 changes: 8 additions & 5 deletions docs/tutorials/helloworld.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ In this section we will create the basic building blocks of a multiplayer game.

### Creating Network Manager and selecting the Transport

In this section we will add a Network Manager and add Unity Transport (UTP) to our project.
In this section we will add a Network Manager and add Unity Transport (UTP) to our project. The [NetworkManager](../components/networkmanager.md) is the component that contains all of your project's netcode related settings. UTP is the transport layer that Netcode will use for communication between the server and the clients. See [here](../advanced-topics/transports.md) for more.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slight reword suggestion:

In this section, we add a Network Manager and Unity Transport (UTP) to our project. The NetworkManager is the component that contains all your project's netcode-related settings. UTP is the transport layer that Netcode uses for communication between the server and the clients. See here for more.


1. Right-click in the **Hierarchy** tab of the main Unity Window.
1. Select **Create Empty**.
Expand Down Expand Up @@ -89,7 +89,7 @@ When 'Enable Scene Management' is enabled for the NetworkManager (allowing the s

## Creating a command line helper

This command line helper launches our project outside Unity and can make testing builds easier.
This command line helper will allow us to launch builds with a command line argument that will start a networking session, either as a server, host, or client. This can make testing builds easier.

1. Right-click the **Assets** folder and create a new folder by hovering over **Create** and selecting **Folder**. Name it **Scripts**.
2. Create a script called `NetworkCommandLine` by right-clicking on your **Scripts** folder, hovering over **Create** and selecting **C# Script**.
Expand Down Expand Up @@ -290,16 +290,19 @@ import TabItem from '@theme/TabItem';

## Testing Hello World

Now we will test to see if everything works as expected.
Now, to see if everything works as expected we can test starting a host in the editor. A host plays the role of a server and a client at the same time.

1. Click **Play**.
1. Click **Start Host** under **NetworkManager**.
1. Click the **Start Host** button in the **NetworkManager** GameObject's inspector.
1. You should now see your scene with your Player Prefab spawned.

You can also use the command line helper to launch a server and one or more client that will connect to the server. You should then see the plane on the server, until the first client connects. Then, for each connected client, a new Player Prefab will be spawned.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor suggestion:

You can also use the command line helper to launch a server and one or more clients to connect to the server. You should see the plane on the server until the first client connects. Then, a new Player Prefab will be spawned for each connected client.

What spawns the new Player Prefabs for each connected client?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I'll clarify this


## Next Steps

See the following content to continue your journey using Netcode:

* Build on the Hello World project to continue learning about different features of Netcode with the [Golden Path series](../tutorials/goldenpath_series/gp_intro.md).
* Build on the Hello World project to continue learning about different features of Netcode with the [Golden Path series](goldenpath_series/gp_intro.md).
* Check out the educational samples to further explore Netcode and its abilities:
* [Boss Room](../learn/bossroom/getting-started-boss-room.md)
* [2D Spaceshooter Bitesize Sample](../learn/bitesize/bitesize-spaceshooter.md)
Expand Down