Skip to content

Commit dd4a7a7

Browse files
noellie-velezNoelStephensUnityjabbacakes
authored
fix: add flag dedicated server override v2.x (#3760)
* Moving command line options to unity transport * Remove Override and ParseArgs * Add flag to force cli args override in SetConnectionData * Creating a command line option class + singleton * Init command-line options singleton only when used * Remove redundant ushort cast Co-authored-by: Noel Stephens <[email protected]> * Fix maxnumberplayers documentation Note Co-authored-by: Noel Stephens <[email protected]> * Added -ip command line option * Update: check force override command line args flag also for address and not only for port @NoelStephensUnity suggestion * Adding hyphen to command-line arguments Co-authored-by: Amy Reeve <[email protected]> * Rewording Co-authored-by: Amy Reeve <[email protected]> * Adding additional resources Co-authored-by: Amy Reeve <[email protected]> * Styling Co-authored-by: Amy Reeve <[email protected]> * Apply suggestions from docs code review (Titles in sentence case, adding a hyphen to `command-line arguments` and styling) Co-authored-by: Amy Reeve <[email protected]> * Avoid changing public method layout @NoelStephensUnity suggestion to create an override * Fix SetConnectionData ambiguous call --------- Co-authored-by: Noel Stephens <[email protected]> Co-authored-by: Amy Reeve <[email protected]>
1 parent 38079c9 commit dd4a7a7

File tree

10 files changed

+216
-60
lines changed

10 files changed

+216
-60
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +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+
- 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)
1416

1517

1618
### Changed
@@ -27,7 +29,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
2729
- Fixed issues with the "Client-server quickstart for Netcode for GameObjects" script having static methods and properties. (#3787)
2830
- 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)
2931
- Fixed issue where the `Axis to Synchronize` toggles didn't work with multi object editing in `NetworkTransform`. (#3781)
30-
32+
- Fixed issue where using the dedicated server package would override all attempts to change the port by code. (#3760)
3133

3234
### Security
3335

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. |
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.

com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -974,19 +974,6 @@ public NetworkPrefabHandler PrefabHandler
974974
internal NetworkConnectionManager ConnectionManager = new NetworkConnectionManager();
975975
internal NetworkMessageManager MessageManager = null;
976976

977-
internal struct Override<T>
978-
{
979-
private T m_Value;
980-
public bool Overidden { get; private set; }
981-
internal T Value
982-
{
983-
get { return Overidden ? m_Value : default(T); }
984-
set { Overidden = true; m_Value = value; }
985-
}
986-
};
987-
988-
internal Override<ushort> PortOverride;
989-
990977
/// <summary>
991978
/// Determines if the NetworkManager's GameObject is parented under another GameObject and
992979
/// notifies the user that this is not allowed for the NetworkManager.
@@ -1166,8 +1153,6 @@ internal void Initialize(bool server)
11661153
return;
11671154
}
11681155

1169-
ParseCommandLineOptions();
1170-
11711156
if (NetworkConfig.NetworkTransport == null)
11721157
{
11731158
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
@@ -1738,40 +1723,6 @@ private void OnDestroy()
17381723
#endif
17391724
}
17401725

1741-
// Command line options
1742-
private const string k_OverridePortArg = "-port";
1743-
1744-
private string GetArg(string[] commandLineArgs, string arg)
1745-
{
1746-
var argIndex = Array.IndexOf(commandLineArgs, arg);
1747-
if (argIndex >= 0 && argIndex < commandLineArgs.Length - 1)
1748-
{
1749-
return commandLineArgs[argIndex + 1];
1750-
}
1751-
1752-
return null;
1753-
}
1754-
1755-
private void ParseArg<T>(string arg, ref Override<T> value)
1756-
{
1757-
if (GetArg(Environment.GetCommandLineArgs(), arg) is string argValue)
1758-
{
1759-
value.Value = (T)Convert.ChangeType(argValue, typeof(T));
1760-
}
1761-
}
1762-
1763-
private void ParseCommandLineOptions()
1764-
{
1765-
#if UNITY_SERVER && UNITY_DEDICATED_SERVER_ARGUMENTS_PRESENT
1766-
if ( UnityEngine.DedicatedServer.Arguments.Port != null)
1767-
{
1768-
PortOverride.Value = (ushort)UnityEngine.DedicatedServer.Arguments.Port;
1769-
}
1770-
#else
1771-
ParseArg(k_OverridePortArg, ref PortOverride);
1772-
#endif
1773-
}
1774-
17751726
#if UNITY_EDITOR
17761727
internal static INetworkManagerHelper NetworkManagerHelper;
17771728

com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,40 @@ public void SetClientRelayData(string ipAddress, ushort port, byte[] allocationI
805805
SetRelayServerData(ipAddress, port, allocationId, key, connectionData, hostConnectionData, isSecure);
806806
}
807807

808+
// Command line options
809+
private const string k_OverridePortArg = "-port";
810+
private const string k_OverrideIpAddressArg = "-ip";
811+
812+
private bool ParseCommandLineOptionsPort(out ushort port)
813+
{
814+
#if UNITY_SERVER && UNITY_DEDICATED_SERVER_ARGUMENTS_PRESENT
815+
if (UnityEngine.DedicatedServer.Arguments.Port != null)
816+
{
817+
port = (ushort)UnityEngine.DedicatedServer.Arguments.Port;
818+
return true;
819+
}
820+
#else
821+
if (CommandLineOptions.Instance.GetArg(k_OverridePortArg) is string argValue)
822+
{
823+
port = (ushort)Convert.ChangeType(argValue, typeof(ushort));
824+
return true;
825+
}
826+
#endif
827+
port = default;
828+
return false;
829+
}
830+
831+
private bool ParseCommandLineOptionsAddress(out string ipValue)
832+
{
833+
if (CommandLineOptions.Instance.GetArg(k_OverrideIpAddressArg) is string argValue)
834+
{
835+
ipValue = argValue;
836+
return true;
837+
}
838+
ipValue = default;
839+
return false;
840+
}
841+
808842
/// <summary>
809843
/// Sets IP and Port information. This will be ignored if using the Unity Relay and you should call <see cref="SetRelayServerData"/>
810844
/// </summary>
@@ -813,6 +847,29 @@ public void SetClientRelayData(string ipAddress, ushort port, byte[] allocationI
813847
/// <param name="listenAddress">The address the server is going to listen on.</param>
814848
public void SetConnectionData(string ipv4Address, ushort port, string listenAddress = null)
815849
{
850+
SetConnectionData(false, ipv4Address, port, listenAddress);
851+
}
852+
853+
/// <summary>
854+
/// Sets IP and Port information. This will be ignored if using the Unity Relay and you should call <see cref="SetRelayServerData"/>
855+
/// </summary>
856+
/// <param name="ipv4Address">The remote IP address (despite the name, can be an IPv6 address or a domain name).</param>
857+
/// <param name="port">The remote port to connect to.</param>
858+
/// <param name="listenAddress">The address the server is going to listen on.</param>
859+
/// <param name="forceOverrideCommandLineArgs">When true, -port and -ip command line arguments will be ignored.</param>
860+
public void SetConnectionData(bool forceOverrideCommandLineArgs, string ipv4Address, ushort port, string listenAddress = null)
861+
{
862+
m_HasForcedConnectionData = forceOverrideCommandLineArgs;
863+
if (!forceOverrideCommandLineArgs && ParseCommandLineOptionsPort(out var commandLinePort))
864+
{
865+
port = commandLinePort;
866+
}
867+
868+
if (!forceOverrideCommandLineArgs && ParseCommandLineOptionsAddress(out var commandLineIp))
869+
{
870+
ipv4Address = commandLineIp;
871+
}
872+
816873
ConnectionData = new ConnectionAddressData
817874
{
818875
Address = ipv4Address,
@@ -1566,6 +1623,11 @@ protected override string GetDisconnectEventMessage(DisconnectEvents disconnectE
15661623
return m_UnityTransportNotificationHandler.GetDisconnectEventMessage(disconnectEvent);
15671624
}
15681625

1626+
/// <summary>
1627+
/// This is set in <see cref="SetConnectionData(string, ushort, string, bool)"/>
1628+
/// </summary>
1629+
private bool m_HasForcedConnectionData;
1630+
15691631
/// <summary>
15701632
/// Initializes the transport
15711633
/// </summary>
@@ -1579,12 +1641,23 @@ public override void Initialize(NetworkManager networkManager = null)
15791641
return;
15801642
}
15811643
#endif
1582-
15831644
m_NetworkManager = networkManager;
15841645

1585-
if (m_NetworkManager && m_NetworkManager.PortOverride.Overidden)
1646+
//If the port doesn't have a forced value and is set by a command line option, override it.
1647+
if (!m_HasForcedConnectionData && ParseCommandLineOptionsAddress(out var portAsString))
15861648
{
1587-
ConnectionData.Port = m_NetworkManager.PortOverride.Value;
1649+
if (m_NetworkManager?.LogLevel <= LogLevel.Developer)
1650+
{
1651+
Debug.Log($"The port is set by a command line option. Using following connection data: {ConnectionData.Address}:{portAsString}");
1652+
}
1653+
if (ushort.TryParse(portAsString, out ushort port))
1654+
{
1655+
ConnectionData.Port = port;
1656+
}
1657+
else
1658+
{
1659+
Debug.LogError($"The port ({portAsString}) is not a valid unsigned short value!");
1660+
}
15881661
}
15891662

15901663
m_RealTimeProvider = m_NetworkManager ? m_NetworkManager.RealTimeProvider : new RealTimeProvider();

com.unity.netcode.gameobjects/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "com.unity.netcode.gameobjects",
33
"displayName": "Netcode for GameObjects",
44
"description": "Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.",
5-
"version": "2.8.0",
5+
"version": "2.9.0",
66
"unity": "6000.0",
77
"dependencies": {
88
"com.unity.nuget.mono-cecil": "1.11.4",

0 commit comments

Comments
 (0)