-
Notifications
You must be signed in to change notification settings - Fork 225
fix: tutorial improvements #840
Changes from 11 commits
bc0bbf5
a047129
54595dc
572a15d
4b7d664
d2eb970
b58f304
f570d18
9e04ba1
0d167c7
301b201
2aa8b23
028b561
85c1a00
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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. | ||
|
@@ -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> | ||
|
@@ -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. | ||
|
||
We call these methods inside of `OnGUI()`. | ||
|
||
|
@@ -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. | ||
|
@@ -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). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I took a shot at rewording this paragraph a bit, but some things still aren't clear to me:
I want to convert this to active voice, but I'm unsure what spawns the script instance.
It's not clear what "this" refers to here. Is it referring to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
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
Yes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In that case, how does this sound? :D
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 😅 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Slight reword suggestion:
|
||
|
||
1. Right-click in the **Hierarchy** tab of the main Unity Window. | ||
1. Select **Create Empty**. | ||
|
@@ -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**. | ||
|
@@ -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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor suggestion:
What spawns the new Player Prefabs for each connected client? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this sound?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
much better