Skip to content

Commit f3926e5

Browse files
Merge branch 'develop-2.0.0' into fix/server-sending-disconnectmessage-to-self
2 parents 4c0ab7c + dd4a7a7 commit f3926e5

File tree

11 files changed

+241
-81
lines changed

11 files changed

+241
-81
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ Additional documentation and release notes are available at [Multiplayer Documen
1111
### Added
1212

1313
- It is now possible to control which port clients will bind to using the `UnityTransport.ConnectionData.ClientBindPort` field. If not set, clients will bind to an ephemeral port (same as before this change). (#3764)
14-
14+
- Added a flag to override command-line arguments (port and ip) in `SetConnectionData`. (#3760)
15+
- Added a command-line singleton to parse environment command-line arguments. (#3760)
1516

1617
### Changed
1718

@@ -25,11 +26,12 @@ Additional documentation and release notes are available at [Multiplayer Documen
2526

2627
### Fixed
2728

29+
- Fixed issues with the "Client-server quickstart for Netcode for GameObjects" script having static methods and properties. (#3787)
2830
- Fixed issue where a warning message was being logged upon a client disconnecting from a server when the log level is set to developer. (#3786)
2931
- Fixed issue where the server or host would no longer have access to the transport id to client id table when processing a transport level client disconnect event. (#3786)
3032
- Fixed issue where invoking an RPC, on another `NetworkBehaviour` associated with the same `NetworkObject` that is ordered before the `NetworkBehaviour` invoking the RPC, during `OnNetworkSpawn` could throw an exception if scene management is disabled. (#3782)
3133
- Fixed issue where the `Axis to Synchronize` toggles didn't work with multi object editing in `NetworkTransform`. (#3781)
32-
34+
- Fixed issue where using the dedicated server package would override all attempts to change the port by code. (#3760)
3335

3436
### Security
3537

com.unity.netcode.gameobjects/Documentation~/TableOfContents.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* [Max players](basics/maxnumberplayers.md)
2020
* [Transports](advanced-topics/transports.md)
2121
* [Unity Relay](relay/relay.md)
22+
* [Command-line arguments](command-line-arguments.md)
2223
* [Network components](network-components.md)
2324
* [Core components](components/core/corecomponents.md)
2425
* [NetworkObject](components/core/networkobject.md)

com.unity.netcode.gameobjects/Documentation~/basics/maxnumberplayers.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ if( m_Portal.NetManager.ConnectedClientsIds.Count >= CharSelectData.k_MaxLobbyPl
2121
}
2222
```
2323

24-
> [!NOTE]
24+
> [!NOTE]
2525
> In connection approval delegate, Netcode for GameObjects doesn't support sending anything more than a Boolean back.
2626
2727
<!-- Commenting this out until we can get external code references working
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Command-line arguments
2+
3+
Use [command-line arguments](https://docs.unity3d.com/Documentation/Manual/CommandLineArguments.html) to configure certain aspects of your game at launch. This is especially useful for dedicated server builds, where arguments let you override default network settings such as the IP address and port.
4+
5+
## Using command-line arguments
6+
7+
When launching a standalone build (such as a headless dedicated server), you can supply custom arguments to modify runtime behavior.
8+
9+
Reserved arguments:
10+
11+
- `-port`
12+
- `-ip`
13+
14+
Unity provides built-in parsing for standard arguments, and you can extend this behavior by adding your own.
15+
16+
## Custom arguments
17+
18+
You can define additional custom command-line arguments and retrieve them through the `CommandLineOptions` class. Use `GetArgs()` in your project code to collect and process these values.
19+
20+
> [!NOTE]
21+
> Adding a custom command-line argument requires you to explicitly retrieve and handle it in your implementation.
22+
23+
## Example
24+
25+
The following code shows you an example of defining and then reading a custom command-line argument.
26+
```
27+
private const string k_OverrideArg = "-argName";
28+
29+
private bool ParseCommandLineOptions(out string command)
30+
{
31+
if (CommandLineOptions.Instance.GetArg(k_OverrideArg) is string argValue)
32+
{
33+
command = argValue;
34+
return true;
35+
}
36+
command = default;
37+
return false;
38+
}
39+
```
40+
41+
Usage example:
42+
43+
```
44+
if (ParseCommandLineOptions(out var command))
45+
{
46+
// Your logic here
47+
}
48+
```
49+
50+
## Override connection data
51+
52+
If you want to ignore the connection port provided through command-line arguments, you can override it by using the optional `forceOverride` parameter in:
53+
54+
```
55+
UnityTransport.SetConnectionData(string ip, ushort port, string listenAddress, bool forceOverride);
56+
```
57+
58+
Setting `forceOverride` to `true` ensures that the values you pass to `SetConnectionData` override any values specified via command-line arguments.
59+
60+
## Additional resources
61+
62+
- [Command-line arguments in the Unity Manual](https://docs.unity3d.com/6000.2/Documentation/Manual/CommandLineArguments.html)

com.unity.netcode.gameobjects/Documentation~/configuration.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
Configure your Netcode for GameObjects project.
44

5-
| **Topic** | **Description** |
6-
| :------------------------------ | :------------------------------- |
7-
| **[Configuring connections](configure-connections.md)** | Configure connections in your project. |
8-
| **[Transports](advanced-topics/transports.md)**| Transport layers establish communication between your application and different hosts in a network. |
9-
| **[Unity Relay](relay/relay.md)**| Use Unity Relay with Netcode for GameObjects to connect clients and hosts over the internet using a relay server. |
5+
6+
| **Topic** | **Description** |
7+
|:--------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------|
8+
| **[Configuring connections](configure-connections.md)** | Configure connections in your project. |
9+
| **[Transports](advanced-topics/transports.md)** | Transport layers establish communication between your application and different hosts in a network. |
10+
| **[Unity Relay](relay/relay.md)** | Use Unity Relay with Netcode for GameObjects to connect clients and hosts over the internet using a relay server. |
11+
| **[Command-line arguments](command-line-arguments.md)** | Use command-line arguments to configure certain aspects of your game at launch. |

com.unity.netcode.gameobjects/Documentation~/tutorials/get-started-with-ngo.md

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -142,16 +142,20 @@ using UnityEngine;
142142

143143
namespace HelloWorld
144144
{
145+
/// <summary>
146+
/// Add this component to the same GameObject as
147+
/// the NetworkManager component.
148+
/// </summary>
145149
public class HelloWorldManager : MonoBehaviour
146150
{
147151
private NetworkManager m_NetworkManager;
148152

149-
void Awake()
153+
private void Awake()
150154
{
151155
m_NetworkManager = GetComponent<NetworkManager>();
152156
}
153157

154-
void OnGUI()
158+
private void OnGUI()
155159
{
156160
GUILayout.BeginArea(new Rect(10, 10, 300, 300));
157161
if (!m_NetworkManager.IsClient && !m_NetworkManager.IsServer)
@@ -168,14 +172,14 @@ namespace HelloWorld
168172
GUILayout.EndArea();
169173
}
170174

171-
static void StartButtons()
175+
private void StartButtons()
172176
{
173177
if (GUILayout.Button("Host")) m_NetworkManager.StartHost();
174178
if (GUILayout.Button("Client")) m_NetworkManager.StartClient();
175179
if (GUILayout.Button("Server")) m_NetworkManager.StartServer();
176180
}
177181

178-
static void StatusLabels()
182+
private void StatusLabels()
179183
{
180184
var mode = m_NetworkManager.IsHost ?
181185
"Host" : m_NetworkManager.IsServer ? "Server" : "Client";
@@ -185,11 +189,11 @@ namespace HelloWorld
185189
GUILayout.Label("Mode: " + mode);
186190
}
187191

188-
static void SubmitNewPosition()
192+
private void SubmitNewPosition()
189193
{
190194
if (GUILayout.Button(m_NetworkManager.IsServer ? "Move" : "Request Position Change"))
191195
{
192-
if (m_NetworkManager.IsServer && !m_NetworkManager.IsClient )
196+
if (m_NetworkManager.IsServer && !m_NetworkManager.IsClient)
193197
{
194198
foreach (ulong uid in m_NetworkManager.ConnectedClientsIds)
195199
m_NetworkManager.SpawnManager.GetPlayerNetworkObject(uid).GetComponent<HelloWorldPlayer>().Move();
@@ -215,14 +219,14 @@ In your Hello World project, you created a NetworkManager by adding the pre-crea
215219
The `HelloWorldManager.cs` script accomplishes this menu within the `StartButtons().` After you select a button, the `StatusLabels()`method adds a label on-screen to display which mode you have selected. This helps distinguish Game view windows from each other when testing your multiplayer game.
216220

217221
```csharp
218-
static void StartButtons()
222+
private void StartButtons()
219223
{
220224
if (GUILayout.Button("Host")) NetworkManager.Singleton.StartHost();
221225
if (GUILayout.Button("Client")) NetworkManager.Singleton.StartClient();
222226
if (GUILayout.Button("Server")) NetworkManager.Singleton.StartServer();
223227
}
224228

225-
static void StatusLabels()
229+
private void StatusLabels()
226230
{
227231
var mode = NetworkManager.Singleton.IsHost ?
228232
"Host" : NetworkManager.Singleton.IsServer ? "Server" : "Client";
@@ -274,7 +278,7 @@ public class RpcTest : NetworkBehaviour
274278
}
275279

276280
[Rpc(SendTo.ClientsAndHost)]
277-
void ClientAndHostRpc(int value, ulong sourceNetworkObjectId)
281+
private void ClientAndHostRpc(int value, ulong sourceNetworkObjectId)
278282
{
279283
Debug.Log($"Client Received the RPC #{value} on NetworkObject #{sourceNetworkObjectId}");
280284
if (IsOwner) //Only send an RPC to the owner of the NetworkObject
@@ -284,7 +288,7 @@ public class RpcTest : NetworkBehaviour
284288
}
285289

286290
[Rpc(SendTo.Server)]
287-
void ServerOnlyRpc(int value, ulong sourceNetworkObjectId)
291+
private void ServerOnlyRpc(int value, ulong sourceNetworkObjectId)
288292
{
289293
Debug.Log($"Server Received the RPC #{value} on NetworkObject #{sourceNetworkObjectId}");
290294
ClientAndHostRpc(value, sourceNetworkObjectId);
@@ -375,7 +379,7 @@ namespace HelloWorld
375379
}
376380

377381
[Rpc(SendTo.Server)]
378-
void SubmitPositionRequestRpc(RpcParams rpcParams = default)
382+
private void SubmitPositionRequestRpc(RpcParams rpcParams = default)
379383
{
380384
var randomPosition = GetRandomPositionOnPlane();
381385
transform.position = randomPosition;
@@ -387,7 +391,7 @@ namespace HelloWorld
387391
return new Vector3(Random.Range(-3f, 3f), 1f, Random.Range(-3f, 3f));
388392
}
389393

390-
void Update()
394+
private void Update()
391395
{
392396
transform.position = Position.Value;
393397
}
@@ -408,7 +412,7 @@ public class HelloWorldPlayer : NetworkBehaviour
408412
For multiplayer games, every object runs on at least two machines: player one and player two. Because of this, you need to ensure both machines have the same behavior and have the correct information about the object. One of the instances that come into play then is to understand how the Player moves. Only one player controls how the Player object moves. The following code enforces this by validating if the machine running the code is the player's owner.
409413

410414
```csharp
411-
public override void OnNetworkSpawn()
415+
public override void OnNetworkSpawn()
412416
{
413417
if (IsOwner)
414418
{
@@ -430,14 +434,14 @@ If the current player is the server, the code determines a random position to sp
430434
}
431435

432436
[Rpc(SendTo.Server)]
433-
void SubmitPositionRequestRpc(RpcParams rpcParams = default)
437+
private void SubmitPositionRequestRpc(RpcParams rpcParams = default)
434438
{
435439
var randomPosition = GetRandomPositionOnPlane();
436440
transform.position = randomPosition;
437441
Position.Value = randomPosition;
438442
}
439443

440-
void Update()
444+
private void Update()
441445
{
442446
transform.position = Position.Value;
443447
}
@@ -458,8 +462,8 @@ You can call this `Rpc` when the player is a client or a server. When you call a
458462
The `Rpc` sets the position NetworkVariable on the server's instance of the player by just picking a random point on the plane.
459463

460464
```csharp
461-
[Rpc(SendTo.Server)]
462-
void SubmitPositionRequestRpc(RpcParams rpcParams = default)
465+
[Rpc(SendTo.Server)]
466+
private void SubmitPositionRequestRpc(RpcParams rpcParams = default)
463467
{
464468
var randomPosition = GetRandomPositionOnPlane();
465469
transform.position = randomPosition;
@@ -470,7 +474,7 @@ The `Rpc` sets the position NetworkVariable on the server's instance of the play
470474
The server instance of the player modifies the `Position` `NetworkVariable` through the `Rpc`. If the player is a client, it must apply the position locally inside the `Update` loop. (Since the two values are the same on the server, the server can run the same logic with no side effects, but you could also add `if(IsClient)` here.)
471475

472476
```csharp
473-
void Update()
477+
private void Update()
474478
{
475479
transform.position = Position.Value;
476480
}
@@ -479,7 +483,7 @@ The server instance of the player modifies the `Position` `NetworkVariable` thro
479483
Because the `HelloWorldPlayer.cs` script handles the position NetworkVariable, the `HelloWorldManager.cs` script can define the contents of `SubmitNewPosition()`.
480484

481485
```csharp
482-
static void SubmitNewPosition()
486+
private void SubmitNewPosition()
483487
{
484488
if (GUILayout.Button(NetworkManager.Singleton.IsServer ? "Move" : "Request Position Change"))
485489
{
@@ -550,7 +554,7 @@ using UnityEngine;
550554

551555
public class NetworkTransformTest : NetworkBehaviour
552556
{
553-
void Update()
557+
private void Update()
554558
{
555559
if (IsServer)
556560
{
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using UnityEngine;
4+
5+
namespace Unity.Netcode
6+
{
7+
/// <summary>
8+
/// This class contains a list of the application instance domain's command line arguments that
9+
/// are used when entering PlayMode or the build is executed.
10+
/// </summary>
11+
public class CommandLineOptions
12+
{
13+
/// <summary>
14+
/// Command-line options singleton
15+
/// </summary>
16+
public static CommandLineOptions Instance
17+
{
18+
get
19+
{
20+
if (s_Instance == null)
21+
{
22+
s_Instance = new CommandLineOptions();
23+
}
24+
return s_Instance;
25+
}
26+
private set
27+
{
28+
s_Instance = value;
29+
}
30+
}
31+
private static CommandLineOptions s_Instance;
32+
33+
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
34+
private static void RuntimeInitializeOnLoad() => Instance = new CommandLineOptions();
35+
36+
// Contains the current application instance domain's command line arguments
37+
internal static List<string> CommandLineArguments = new List<string>();
38+
39+
// Invoked upon application start, after scene load
40+
[RuntimeInitializeOnLoadMethod]
41+
private static void ParseCommandLineArguments()
42+
{
43+
// Get all the command line arguments to be parsed later and/or modified
44+
// prior to being parsed (for testing purposes).
45+
CommandLineArguments = new List<string>(Environment.GetCommandLineArgs());
46+
}
47+
48+
/// <summary>
49+
/// Returns the value of an argument or null if there the argument is not present
50+
/// </summary>
51+
/// <param name="arg">The name of the argument</param>
52+
/// <returns><see cref="string"/>Value of the command line argument passed in.</returns>
53+
public string GetArg(string arg)
54+
{
55+
var argIndex = CommandLineArguments.IndexOf(arg);
56+
if (argIndex >= 0 && argIndex < CommandLineArguments.Count - 1)
57+
{
58+
return CommandLineArguments[argIndex + 1];
59+
}
60+
return null;
61+
}
62+
}
63+
}

com.unity.netcode.gameobjects/Runtime/Configuration/CommandLineOptions.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)