您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

285 行
10 KiB

using System;
using Unity.Services.Authentication;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using Unity.Services.Core;
using Unity.Services.Lobbies;
using Unity.Services.Lobbies.Models;
using Unity.Services.Relay;
using UnityEngine;
using Debug = UnityEngine.Debug;
public class LobbyAndRelayTester : MonoBehaviour
{
[SerializeField]
string m_JoinCode;
[SerializeField]
string m_RelayCode;
[SerializeField]
bool m_Host;
Guid m_RelayAllocationId;
bool m_InLobby;
string m_WorkingLobbyId;
string m_PlayerId;
Timer m_Time;
Lobby m_CurrentLobby;
// This is handled in the LobbyAsyncRequest calls normally, but we need to supply this for the dir
Dictionary<string, PlayerDataObject> m_MockUserData;
UnityTransport m_UnityTransport;
NetworkManager m_NetworkManager;
CancellationTokenSource m_CancellationTokenSource;
Stopwatch m_timer;
// Start is called before the first frame update
public async void Start()
{
var profileName = m_Host ? "host" : "client";
var initOptions = new InitializationOptions().SetProfile(profileName);
await UnityServices.InitializeAsync(initOptions);
await AuthenticationService.Instance.SignInAnonymouslyAsync();
m_NetworkManager = NetworkManager.Singleton;
m_timer = new Stopwatch();
m_timer.Start();
m_UnityTransport = m_NetworkManager.GetComponent<UnityTransport>();
m_PlayerId = AuthenticationService.Instance.PlayerId;
m_CancellationTokenSource = new CancellationTokenSource();
var cancellationToken = m_CancellationTokenSource.Token;
Debug.Log($"Starting as: {profileName} - {m_PlayerId}");
if (m_Host)
{
var hostLobby = await Host_Relay_Lobby();
if (hostLobby == null)
return;
m_JoinCode = hostLobby.LobbyCode;
#pragma warning disable 4014
KeepLobbyAlive(hostLobby, cancellationToken);
#pragma warning restore 4014
}
else
{
await Join_Disconnect_Test();
}
await PollLobby(cancellationToken);
}
async Task KeepLobbyAlive(Lobby lobby, CancellationToken cancel)
{
m_InLobby = true;
var kickedPlayer = false;
while (m_InLobby && !cancel.IsCancellationRequested)
{
await Task.Delay(9000);
await LobbyService.Instance.SendHeartbeatPingAsync(lobby.Id);
Debug.Log("HeartBeat.");
}
}
async Task PollLobby(CancellationToken cancel)
{
m_InLobby = true;
while (m_InLobby && !cancel.IsCancellationRequested)
{
await Task.Delay(3000);
m_CurrentLobby = await LobbyService.Instance.GetLobbyAsync(m_CurrentLobby.Id);
Debug.Log(
$"Polled Lobby @ {m_timer.Elapsed.Minutes} : {m_timer.Elapsed.Seconds}.\nID:{m_CurrentLobby.Id} HostID:{m_CurrentLobby.HostId} " +
$"- Code: {m_CurrentLobby.LobbyCode} - Players: {m_CurrentLobby.Players.Count} - Private: {m_CurrentLobby.IsPrivate}");
}
}
async Task<Lobby> Host_Relay_Lobby()
{
var allocation = await Relay.Instance.CreateAllocationAsync(3, null);
m_RelayAllocationId = allocation.AllocationId;
Debug.Log($"RelayAllocation : {m_RelayAllocationId} " +
$"- {allocation.RelayServer.IpV4} : {allocation.RelayServer.Port}");
StringBuilder sb = new StringBuilder("Endpoints: \n");
foreach (var endpoint in allocation.ServerEndpoints)
{
sb.AppendLine($"Host: {endpoint.Host} - ConnectionType: {endpoint.ConnectionType} " +
$"- Port: {endpoint.Port} - Secure?:{endpoint.Secure}");
}
Debug.Log(sb);
m_UnityTransport.SetHostRelayData(allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port,
allocation.AllocationIdBytes, allocation.Key, allocation.ConnectionData);
// Start Host
m_NetworkManager.StartHost();
// Generate Join_Relay_Lobby Code
m_RelayCode = await Relay.Instance.GetJoinCodeAsync(m_RelayAllocationId);
// Create Lobby
var options = new CreateLobbyOptions
{
Data = new Dictionary<string, DataObject>
{
{ "relayJoinCode", new DataObject(DataObject.VisibilityOptions.Public, m_RelayCode) },
},
Player = new Player(m_PlayerId, allocationId: m_RelayAllocationId.ToString())
};
m_CurrentLobby = await LobbyService.Instance.CreateLobbyAsync("testLobby", 3, options);
return m_CurrentLobby;
}
async Task<Lobby> Join_Relay_Lobby(string lobbyId, string password = "")
{
var player = new Player(m_PlayerId);
var options = new JoinLobbyByCodeOptions
{
Player = player,
};
m_CurrentLobby = await LobbyService.Instance.JoinLobbyByCodeAsync(lobbyId, options);
Debug.Log($"Joined Lobby: {m_CurrentLobby.Id} - {m_CurrentLobby.Players.Count}");
m_RelayCode = m_CurrentLobby.Data["relayJoinCode"].Value;
Debug.Log($"Joined Lobby: {m_CurrentLobby.Id} - {m_CurrentLobby.Players.Count} - RelayCode:{m_RelayCode}");
var joinAllocation = await Relay.Instance.JoinAllocationAsync(m_RelayCode);
await Lobbies.Instance.UpdatePlayerAsync(m_CurrentLobby.Id, player.Id,
new UpdatePlayerOptions
{
AllocationId = joinAllocation.AllocationId.ToString()
});
Debug.Log($"Joined Lobby: {m_CurrentLobby.Id} - {m_CurrentLobby.Players.Count} - RelayCode:{m_RelayCode}");
m_UnityTransport.SetClientRelayData(joinAllocation.RelayServer.IpV4, (ushort)joinAllocation.RelayServer.Port,
joinAllocation.AllocationIdBytes, joinAllocation.Key, joinAllocation.ConnectionData,
joinAllocation.HostConnectionData, false);
if (!m_NetworkManager.StartClient())
{
Debug.Log("Could not start client?");
}
return m_CurrentLobby;
}
async Task Host_Disconnect_Test()
{
var lobby = await Host_Relay_Lobby();
Debug.Log($"Created Lobby {lobby.Players.Count}");
var kicked = false;
var callbacks = new LobbyEventCallbacks();
callbacks.KickedFromLobby += () =>
{
Debug.Log("GOT KICKED!");
kicked = true;
};
await LobbyService.Instance.SubscribeToLobbyEventsAsync(lobby.Id, callbacks);
await Task.Delay(5000); // Give it a moment
//Local Disconnect
NetworkManager.Singleton.Shutdown();
//Wait for either the Lobby to signal that we were kicked, or for the time to run out. (Tested with up to 30s, still
await Task.WhenAny(Task.Delay(10000), WaitForKicked());
async Task WaitForKicked()
{
while (!kicked)
await Task.Delay(50);
}
var getPostKickLobbyData = await LobbyService.Instance.GetLobbyAsync(lobby.Id);
var getRelay = await Relay.Instance.JoinAllocationAsync(getPostKickLobbyData.Data["relayJoinCode"].Value);
Debug.Log(
$"RelayAllocation : {getRelay.AllocationId} - {getRelay.RelayServer.IpV4} : {getRelay.RelayServer.Port}");
StringBuilder sb = new StringBuilder("Endpoints: \n");
foreach (var endpoint in getRelay.ServerEndpoints)
{
sb.AppendLine(
$"Host: {endpoint.Host} - ConnectionType: {endpoint.ConnectionType} -Port: {endpoint.Port} - Secure?:{endpoint.Secure}");
}
Debug.Log($"Was {m_PlayerId} kicked? Lobby has {getPostKickLobbyData.Players.Count} player(s)");
foreach (var player in getPostKickLobbyData.Players)
{
Debug.Log($"Player: {player.Id}");
}
}
//need to start the lobby host in one instance and join from another
async Task Join_Disconnect_Test()
{
var lobby = await Join_Relay_Lobby(m_JoinCode);
Debug.Log($"Created Lobby {lobby.Players.Count}");
var kicked = false;
var callbacks = new LobbyEventCallbacks();
callbacks.KickedFromLobby += () =>
{
Debug.Log($"GOT KICKED! @ {m_timer.Elapsed.Minutes} : {m_timer.Elapsed.Seconds}");
kicked = true;
};
await LobbyService.Instance.SubscribeToLobbyEventsAsync(lobby.Id, callbacks);
await Task.Delay(3000);
//Local Disconnect
NetworkManager.Singleton.Shutdown();
//Wait for either the Lobby to signal that we were kicked, or for the time to run out. (Tested with up to 30s, still
await Task.WhenAny(Task.Delay(10000), WaitForKicked());
async Task WaitForKicked()
{
while (!kicked)
{
await Task.Delay(50);
}
}
if (!kicked)
{
Debug.LogError($"Player was not kicked");
}
var getPostKickLobbyData = await LobbyService.Instance.GetLobbyAsync(lobby.Id);
var getRelay = await Relay.Instance.JoinAllocationAsync(getPostKickLobbyData.Data["relayJoinCode"].Value);
Debug.Log(
$"RelayAllocation : {getRelay.AllocationId} - {getRelay.RelayServer.IpV4} : {getRelay.RelayServer.Port}");
StringBuilder sb = new StringBuilder("Endpoints: \n");
foreach (var endpoint in getRelay.ServerEndpoints)
{
sb.AppendLine(
$"Host: {endpoint.Host} - ConnectionType: {endpoint.ConnectionType} -Port: {endpoint.Port} - Secure?:{endpoint.Secure}");
}
Debug.Log($"Lobby has {getPostKickLobbyData.Players.Count} player(s)");
foreach (var player in getPostKickLobbyData.Players)
{
Debug.Log($"Player: {player.Id}");
}
}
public void OnDestroy()
{
m_CancellationTokenSource?.Cancel();
Lobbies.Instance?.DeleteLobbyAsync(m_CurrentLobby.Id);
}
}