Last active
September 21, 2022 18:16
-
-
Save CodeSmile-0000011110110111/d37c7cca0baa3e6d22c6e7ea329ccbd4 to your computer and use it in GitHub Desktop.
Improved Bootstrap example scripts for Unity Netcode for GameObjects, see: https://forum.unity.com/threads/testing-netcode-through-the-internet.1209205/#post-8456006
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using System.Net; | |
using System.Net.NetworkInformation; | |
using System.Net.Sockets; | |
using Unity.Netcode.Transports.UTP; | |
using UnityEngine; | |
namespace Unity.Netcode.Samples | |
{ | |
/// <summary> | |
/// Class to display helper buttons and status labels on the GUI, as well as buttons to start host/client/server. | |
/// Once a connection has been established to the server, the local player can be teleported to random positions via a GUI button. | |
/// </summary> | |
public class BootstrapManager : MonoBehaviour | |
{ | |
private string _hostIpString = "<enter host IP or domain>"; | |
private string _portString = "7777"; | |
private ushort _port; | |
private string _resolvedHostIp = ""; | |
public static string[] GetLocalIPv4(NetworkInterfaceType _type) | |
{ | |
var ipAddrList = new List<string>(); | |
foreach (var item in NetworkInterface.GetAllNetworkInterfaces()) | |
{ | |
if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up) | |
{ | |
foreach (var ip in item.GetIPProperties().UnicastAddresses) | |
{ | |
if (ip.Address.AddressFamily == AddressFamily.InterNetwork) | |
ipAddrList.Add(ip.Address.ToString()); | |
} | |
} | |
} | |
return ipAddrList.ToArray(); | |
} | |
public static IPAddress[] ResolveHostname(string hostName, bool ip6Wanted = false) | |
{ | |
// is it already an IP? | |
if (IPAddress.TryParse(hostName, out var outIpAddress)) | |
return new[] { outIpAddress }; | |
try | |
{ | |
var addresslist = Dns.GetHostAddresses(hostName); | |
if (addresslist == null || addresslist.Length == 0) | |
return new IPAddress[0]; | |
if (ip6Wanted) | |
return addresslist.Where(o => o.AddressFamily == AddressFamily.InterNetworkV6).ToArray(); | |
return addresslist.Where(o => o.AddressFamily == AddressFamily.InterNetwork).ToArray(); | |
} | |
catch {} | |
return null; | |
} | |
private void OnGUI() | |
{ | |
GUILayout.BeginArea(new Rect(10, 10, 300, 300)); | |
var networkManager = NetworkManager.Singleton; | |
var transport = networkManager.GetComponent<UnityTransport>(); | |
_hostIpString = GUILayout.TextField(_hostIpString); | |
_portString = GUILayout.TextField(_portString); | |
var localIP = GetLocalIPv4(NetworkInterfaceType.Ethernet)?.FirstOrDefault(); | |
if (!networkManager.IsClient && !networkManager.IsServer) | |
{ | |
if (GUILayout.Button("Client")) | |
{ | |
_resolvedHostIp = ResolveHostname(_hostIpString)?.FirstOrDefault()?.ToString(); | |
ushort.TryParse(_portString, out _port); | |
print($"Connecting to: {_resolvedHostIp}:{_port}"); | |
transport.SetConnectionData(_resolvedHostIp, _port); | |
networkManager.StartClient(); | |
} | |
GUILayout.Space(40f); | |
var startHost = GUILayout.Button("Host"); | |
var startServer = GUILayout.Button("Server"); | |
if (startHost || startServer) | |
{ | |
localIP = GetLocalIPv4(NetworkInterfaceType.Ethernet).FirstOrDefault(); | |
ushort.TryParse(_portString, out _port); | |
print($"Serving on: {localIP}:{_port}"); | |
transport.SetConnectionData(localIP, _port, "0.0.0.0"); | |
if (startHost) | |
networkManager.StartHost(); | |
if (startServer) | |
networkManager.StartServer(); | |
} | |
} | |
else | |
{ | |
var mode = networkManager.IsHost ? $"Host {localIP}:{_port}" : | |
networkManager.IsServer ? $"Server {localIP}:{_port}" : $"Client connected to {_resolvedHostIp}:{_port}"; | |
GUILayout.Label($"Mode: {mode}"); | |
// "Random Teleport" button will only be shown to clients | |
if (networkManager.IsClient) | |
{ | |
if (GUILayout.Button("Random Teleport")) | |
{ | |
if (networkManager.LocalClient != null) | |
{ | |
// Get `BootstrapPlayer` component from the player's `PlayerObject` | |
if (networkManager.LocalClient.PlayerObject.TryGetComponent(out BootstrapPlayer bootstrapPlayer)) | |
{ | |
// Invoke a `ServerRpc` from client-side to teleport player to a random position on the server-side | |
bootstrapPlayer.RandomTeleportServerRpc(); | |
} | |
} | |
} | |
} | |
} | |
GUILayout.EndArea(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
namespace Unity.Netcode.Samples | |
{ | |
/// <summary> | |
/// Component attached to the "Player Prefab" on the `NetworkManager`. | |
/// </summary> | |
public class BootstrapPlayer : NetworkBehaviour | |
{ | |
private static Vector3 GetRandomPositionOnXYPlane() => new(Random.Range(-5f, 5f), Random.Range(-5f, 5f), 0f); | |
private void Start() | |
{ | |
GetComponent<MeshRenderer>().material.color = IsLocalPlayer ? Color.green : Color.red; | |
if (IsOwner) | |
RandomTeleportServerRpc(); | |
} | |
/// <summary> | |
/// If this method is invoked on the client instance of this player, it will invoke a `ServerRpc` on the server-side. | |
/// If this method is invoked on the server instance of this player, it will teleport player to a random position. | |
/// </summary> | |
/// <remarks> | |
/// Since a `NetworkTransform` component is attached to this player, and the authority on that component is set to "Server", | |
/// this transform's position modification can only be performed on the server, where it will then be replicated down to all clients through `NetworkTransform`. | |
/// </remarks> | |
[ServerRpc] | |
public void RandomTeleportServerRpc() | |
{ | |
var oldPosition = transform.position; | |
transform.position = GetRandomPositionOnXYPlane(); | |
var newPosition = transform.position; | |
print( | |
$"{nameof(RandomTeleportServerRpc)}() -> {nameof(OwnerClientId)}: {OwnerClientId} --- {nameof(oldPosition)}: {oldPosition} --- {nameof(newPosition)}: {newPosition}"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment