您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
147 行
5.8 KiB
147 行
5.8 KiB
using System;
|
|
using System.Threading.Tasks;
|
|
using LobbyRelaySample.relay;
|
|
using Unity.Netcode;
|
|
using Unity.Netcode.Transports.UTP;
|
|
using Unity.Services.Relay;
|
|
using UnityEngine;
|
|
using UnityEngine.SocialPlatforms;
|
|
|
|
namespace LobbyRelaySample.ngo
|
|
{
|
|
/// <summary>
|
|
/// Once the local localPlayer is in a localLobby and that localLobby has entered the In-Game state, this will load in whatever is necessary to actually run the game part.
|
|
/// This will exist in the game scene so that it can hold references to scene objects that spawned prefab instances will need.
|
|
/// </summary>
|
|
public class SetupInGame : MonoBehaviour, IReceiveMessages
|
|
{
|
|
[SerializeField]
|
|
GameObject m_IngameRunnerPrefab = default;
|
|
[SerializeField]
|
|
private GameObject[] m_disableWhileInGame = default;
|
|
|
|
private InGameRunner m_inGameRunner;
|
|
|
|
private bool m_doesNeedCleanup = false;
|
|
private bool m_hasConnectedViaNGO = false;
|
|
|
|
private LocalLobby m_lobby;
|
|
|
|
public void Start()
|
|
{
|
|
Locator.Get.Messenger.Subscribe(this);
|
|
}
|
|
|
|
public void OnDestroy()
|
|
{
|
|
Locator.Get.Messenger.Unsubscribe(this);
|
|
}
|
|
|
|
private void SetMenuVisibility(bool areVisible)
|
|
{
|
|
foreach (GameObject go in m_disableWhileInGame)
|
|
go.SetActive(areVisible);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The prefab with the NetworkManager contains all of the assets and logic needed to set up the NGO minigame.
|
|
/// The UnityTransport needs to also be set up with a new Allocation from Relay.
|
|
/// </summary>
|
|
async Task CreateNetworkManager(LocalLobby localLobby, LocalPlayer localPlayer)
|
|
{
|
|
m_lobby = localLobby;
|
|
m_inGameRunner = Instantiate(m_IngameRunnerPrefab).GetComponentInChildren<InGameRunner>();
|
|
m_inGameRunner.Initialize(OnConnectionVerified, m_lobby.PlayerCount, OnGameEnd, localPlayer);
|
|
if (localPlayer.IsHost.Value)
|
|
{
|
|
await SetRelayHostData();
|
|
NetworkManager.Singleton.StartHost();
|
|
}
|
|
else
|
|
{
|
|
await SetRelayClientData();
|
|
NetworkManager.Singleton.StartClient();
|
|
}
|
|
}
|
|
|
|
async Task SetRelayHostData()
|
|
{
|
|
UnityTransport transport = NetworkManager.Singleton.GetComponentInChildren<UnityTransport>();
|
|
|
|
var allocation = await Relay.Instance.CreateAllocationAsync(m_lobby.MaxPlayerCount.Value);
|
|
var joincode = await Relay.Instance.GetJoinCodeAsync(allocation.AllocationId);
|
|
m_lobby.RelayNGOCode.Value = joincode;
|
|
|
|
bool isSecure = false;
|
|
var endpoint = RelayUtpSetup.GetEndpointForAllocation(allocation.ServerEndpoints,
|
|
allocation.RelayServer.IpV4, allocation.RelayServer.Port, out isSecure);
|
|
|
|
transport.SetHostRelayData(RelayUtpSetup.AddressFromEndpoint(endpoint), endpoint.Port,
|
|
allocation.AllocationIdBytes, allocation.Key, allocation.ConnectionData, isSecure);
|
|
}
|
|
|
|
async Task SetRelayClientData()
|
|
{
|
|
UnityTransport transport = NetworkManager.Singleton.GetComponentInChildren<UnityTransport>();
|
|
|
|
var joinAllocation = await Relay.Instance.JoinAllocationAsync(m_lobby.RelayCode.Value);
|
|
bool isSecure = false;
|
|
var endpoint = RelayUtpSetup.GetEndpointForAllocation(joinAllocation.ServerEndpoints,
|
|
joinAllocation.RelayServer.IpV4, joinAllocation.RelayServer.Port, out isSecure);
|
|
|
|
transport.SetClientRelayData(RelayUtpSetup.AddressFromEndpoint(endpoint), endpoint.Port,
|
|
joinAllocation.AllocationIdBytes, joinAllocation.Key,
|
|
joinAllocation.ConnectionData, joinAllocation.HostConnectionData, isSecure);
|
|
}
|
|
|
|
private void OnConnectionVerified()
|
|
{
|
|
m_hasConnectedViaNGO = true;
|
|
}
|
|
|
|
public void StartNetworkedGame(LocalLobby localLobby, LocalPlayer localPlayer)
|
|
{
|
|
m_doesNeedCleanup = true;
|
|
SetMenuVisibility(false);
|
|
#pragma warning disable 4014
|
|
CreateNetworkManager(localLobby, localPlayer);
|
|
#pragma warning restore 4014
|
|
}
|
|
|
|
public void OnReceiveMessage(MessageType type, object msg)
|
|
{
|
|
if (type == MessageType.ConfirmInGameState) { }
|
|
|
|
else if (type == MessageType.MinigameBeginning)
|
|
{
|
|
if (!m_hasConnectedViaNGO)
|
|
{
|
|
// If this localPlayer hasn't successfully connected via NGO, forcibly exit the minigame.
|
|
Locator.Get.Messenger.OnReceiveMessage(MessageType.DisplayErrorPopup, "Failed to join the game.");
|
|
OnGameEnd();
|
|
}
|
|
}
|
|
else if (type == MessageType.ChangeMenuState)
|
|
{
|
|
// Once we're in-game, any state change reflects the localPlayer leaving the game, so we should clean up.
|
|
OnGameEnd();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return to the localLobby after the game, whether due to the game ending or due to a failed connection.
|
|
/// </summary>
|
|
private void OnGameEnd()
|
|
{
|
|
if (m_doesNeedCleanup)
|
|
{
|
|
NetworkManager.Singleton.Shutdown();
|
|
Destroy(m_inGameRunner
|
|
.gameObject); // Since this destroys the NetworkManager, that will kick off cleaning up networked objects.
|
|
SetMenuVisibility(true);
|
|
m_lobby.RelayNGOCode = null;
|
|
m_doesNeedCleanup = false;
|
|
}
|
|
}
|
|
}
|
|
}
|