浏览代码

Cleaning up with some comments and shifting the RelayNGOUtpSetup to its own file.

/main/staging/ngo_minigame_cleanup
nathaniel.buck@unity3d.com 3 年前
当前提交
1041eaf9
共有 6 个文件被更改,包括 124 次插入123 次删除
  1. 2
      Assets/Scripts/Game/InGame/InGameRunner.cs
  2. 41
      Assets/Scripts/Game/InGame/SetupInGame.cs
  3. 15
      Assets/Scripts/Game/InGame/SymbolContainer.cs
  4. 90
      Assets/Scripts/Relay/RelayUtpSetup.cs
  5. 88
      Assets/Scripts/Game/InGame/RelayNGOUtpSetup.cs
  6. 11
      Assets/Scripts/Game/InGame/RelayNGOUtpSetup.cs.meta

2
Assets/Scripts/Game/InGame/InGameRunner.cs


{
VerifyConnection_ClientRpc(clientId);
// While we could start pooling symbol objects now, incoming clients would be flooded with the Spawn calls.
// This could lead to dropped packets (which would mean data loss), so wait until connections have completed.
// This could lead to dropped packets such that the InGameRunner's Spawn call fails to occur, so we'll wait until all players join.
}
[ClientRpc]
private void VerifyConnection_ClientRpc(ulong clientId)

41
Assets/Scripts/Game/InGame/SetupInGame.cs


private bool m_doesNeedCleanup = false;
private bool m_hasConnectedViaNGO = false;
// TEMP? Relay stuff
/*
* Things to do:
*
* x Disable whatever menu behaviors. Maintain a back button with additional RPC calls?
* --- Need to make RelayUtpClient not an MB so I can freely disable the menus? It is on the GameManager, as it happens, but...
* x Spawn the object with the NetworkManager and allow that to connect.
* - Wait for all players to connect, or boot a player after a few seconds (via Relay) if they did not connect.
* x While waiting, server selects the target sequence, spawns the symbol container, and starts pooling/spawning the symbol objects.
* - Once all players are in, show the target sequence and instructions, and then the server starts moving the symbol container and listening to click events.
* - After the symbols are all passed (I guess tracking the symbol container position or a timeout), finish the game (set the winner flag).
* x Clients clean up and return to the lobby screen. Host sets the lobby back to the regular state.
*
*/
{
Locator.Get.Messenger.Subscribe(this);
{ Locator.Get.Messenger.Subscribe(this);
{
Locator.Get.Messenger.Unsubscribe(this);
{ Locator.Get.Messenger.Unsubscribe(this);
}
private void SetMenuVisibility(bool areVisible)

m_inGameRunner.Initialize(OnConnectionVerified, m_lobby.PlayerCount, OnGameEnd);
UnityTransport transport = m_inGameManagerObj.GetComponentInChildren<UnityTransport>();
m_inGameManagerObj.AddComponent<relay.RelayUtpNGOSetupHost>().Initialize(this, m_lobby, () => { m_initializeTransport(transport); m_networkManager.StartHost(); });
m_inGameManagerObj.AddComponent<inGame.RelayUtpNGOSetupHost>().Initialize(this, m_lobby, () => { m_initializeTransport(transport); m_networkManager.StartHost(); });
m_inGameManagerObj.AddComponent<relay.RelayUtpNGOSetupClient>().Initialize(this, m_lobby, () => { m_initializeTransport(transport); m_networkManager.StartClient(); });
m_inGameManagerObj.AddComponent<inGame.RelayUtpNGOSetupClient>().Initialize(this, m_lobby, () => { m_initializeTransport(transport); m_networkManager.StartClient(); });
{
m_hasConnectedViaNGO = true;
{ m_hasConnectedViaNGO = true;
// These are public for use in the Inspector.
{
m_lobby = lobby; // Most of the time this is redundant, but we need to get multiple members of the lobby to the Relay setup components, so might as well just hold onto the whole thing.
{ m_lobby = lobby; // Most of the time this is redundant, but we need to get multiple members of the lobby to the Relay setup components, so might as well just hold onto the whole thing.
{
m_isHost = user.IsHost;
{ m_isHost = user.IsHost;
}
public void SetRelayServerData(string address, int port, byte[] allocationBytes, byte[] key, byte[] connectionData, byte[] hostConnectionData, bool isSecure)

Locator.Get.Messenger.OnReceiveMessage(MessageType.DisplayErrorPopup, "Failed to join the game.");
// TODO: Need to handle both failing to connect and connecting but failing to initialize.
// I.e. cleaning up networked objects *might* be necessary.
OnGameEnd(); // TODO: This returns to the lobby. I think that's desirable?
OnGameEnd();
}
}

}
}
/// <summary>
/// Return to the lobby after the game, whether due to the game ending or due to a failed connection.
/// </summary>
private void OnGameEnd()
{
if (m_doesNeedCleanup)

15
Assets/Scripts/Game/InGame/SymbolContainer.cs


namespace LobbyRelaySample.inGame
{
// Note: The SymbolObjects, which will be children of this object, need their NetworkTransforms to have IsLocalSpace set to true. Otherwise, they might get desynced.
// (This would manifest as packet loss errors.)
// Also note: The initial position of the SymbolObject prefab is set to be outside the camera view in the Z-direction, so that it doesn't interpolate past the actual
// position when it spawns on a client (as opposed to in the Y-direction, since this SymbolContainer is also moving downward).
/// <summary>
/// Rather than track movement data for every symbol object, the symbols will all be parented under one container that will move.
/// It will not begin that movement until it both has been Spawned on the network and it has been informed that the game has started.
/// </summary>
[RequireComponent(typeof(Rigidbody))]
public class SymbolContainer : NetworkBehaviour, IReceiveMessages
{

public void Start()
{
if (!IsHost)
{ this.enabled = false; // Just disabling this script.
{ this.enabled = false; // Just disabling this script, not the whole GameObject.
return;
}
GetComponent<NetworkObject>().Spawn();

private void BeginMotion()
{
// Note: The SymbolObjects, which will be children of this object, need their NetworkTransforms to have IsLocalSpace set to true. Otherwise, they might get desynced.
// (This would manifest as packet loss errors.)
// Also note: The initial position of the SymbolObject prefab is set to be outside the camera view in the Z-direction, so that it doesn't interpolate past the actual
// position when it spawns on a client (as opposed to in the Y-direction, since this SymbolContainer is also moving downward).
m_rb.velocity = Vector3.down;
}

90
Assets/Scripts/Relay/RelayUtpSetup.cs


protected LobbyUser m_localUser;
protected Action<bool, RelayUtpClient> m_onJoinComplete;
protected static string AddressFromEndpoint(NetworkEndPoint endpoint)
public static string AddressFromEndpoint(NetworkEndPoint endpoint)
{
return endpoint.Address.Split(':')[0];
}

/// Determine the server endpoint for connecting to the Relay server, for either an Allocation or a JoinAllocation.
/// If DTLS encryption is available, and there's a secure server endpoint available, use that as a secure connection. Otherwise, just connect to the Relay IP unsecured.
/// </summary>
protected NetworkEndPoint GetEndpointForAllocation(List<RelayServerEndpoint> endpoints, string ip, int port, out bool isSecure)
public static NetworkEndPoint GetEndpointForAllocation(List<RelayServerEndpoint> endpoints, string ip, int port, out bool isSecure)
{
#if ENABLE_MANAGED_UNITYTLS
foreach (RelayServerEndpoint endpoint in endpoints)

LobbyAsyncRequests.Instance.UpdatePlayerRelayInfoAsync(m_allocation.AllocationId.ToString(), m_localLobby.RelayCode, null);
}
}
}
// TODO: These don't need to be children of RelayUtpSetup, right? Since the binding step isn't used
/*
* When using the Relay adapter for UTP to connect the NetworkManager for Netcode for GameObjects (NGO), we need to provide the Allocation info without manually binding to it.
* In actual use, if you are using NGO for your game's networking, you would not also use the RelayUtpSetupHost/RelayUtpSetupClient at all, since their direct data transmission would be unnecessary.
* We keep both versions for this sample to demonstrate how each is set up, whether you want to just use Lobby + Relay or use NGO as well.
*/
/// <summary>
/// Host logic: Request a new Allocation, and then pass its info to the UTP adapter for NGO.
/// </summary>
public class RelayUtpNGOSetupHost : RelayUtpSetup
{
private inGame.SetupInGame m_setupInGame;
private Action m_onJoin;
public void Initialize(inGame.SetupInGame setupInGame, LocalLobby lobby, Action onJoin)
{
m_setupInGame = setupInGame;
m_localLobby = lobby;
m_onJoin = onJoin;
JoinRelay();
}
protected override void JoinRelay()
{
RelayAPIInterface.AllocateAsync(m_localLobby.MaxPlayerCount, OnAllocation);
}
private void OnAllocation(Allocation allocation)
{
RelayAPIInterface.GetJoinCodeAsync(allocation.AllocationId, OnRelayCode);
bool isSecure = false;
m_endpointForServer = GetEndpointForAllocation(allocation.ServerEndpoints, allocation.RelayServer.IpV4, allocation.RelayServer.Port, out isSecure);
m_setupInGame.SetRelayServerData(AddressFromEndpoint(m_endpointForServer), m_endpointForServer.Port, allocation.AllocationIdBytes, allocation.Key, allocation.ConnectionData, allocation.ConnectionData, isSecure);
m_onJoin?.Invoke();
}
private void OnRelayCode(string relayCode)
{
m_localLobby.RelayNGOCode = relayCode;
}
protected override void OnBindingComplete() { /*No-op*/ }
}
public class RelayUtpNGOSetupClient : RelayUtpSetup
{
private inGame.SetupInGame m_setupInGame;
private Action m_onJoin;
public void Initialize(inGame.SetupInGame setupInGame, LocalLobby lobby, Action onJoin)
{
m_setupInGame = setupInGame;
m_localLobby = lobby;
m_onJoin = onJoin;
JoinRelay();
}
protected override void JoinRelay()
{
m_localLobby.onChanged += OnLobbyChange; // need to unregister to be destroyed
}
private void OnLobbyChange(LocalLobby lobby)
{
if (m_localLobby.RelayNGOCode != null)
{
RelayAPIInterface.JoinAsync(m_localLobby.RelayNGOCode, OnJoin);
m_localLobby.onChanged -= OnLobbyChange;
}
}
private void OnJoin(JoinAllocation joinAllocation)
{
if (joinAllocation == null || this == null) // The returned JoinAllocation is null if allocation failed. this would be destroyed already if you quit the lobby while Relay is connecting.
return;
bool isSecure = false;
m_endpointForServer = GetEndpointForAllocation(joinAllocation.ServerEndpoints, joinAllocation.RelayServer.IpV4, joinAllocation.RelayServer.Port, out isSecure);
m_setupInGame.SetRelayServerData(AddressFromEndpoint(m_endpointForServer), m_endpointForServer.Port, joinAllocation.AllocationIdBytes, joinAllocation.Key, joinAllocation.ConnectionData, joinAllocation.HostConnectionData, isSecure);
m_onJoin?.Invoke();
}
protected override void OnBindingComplete() { /*No-op*/ }
}
}

88
Assets/Scripts/Game/InGame/RelayNGOUtpSetup.cs


using System;
using Unity.Services.Relay.Models;
using UnityEngine;
using LobbyRelaySample.relay;
namespace LobbyRelaySample.inGame
{
/*
* When using the Relay adapter for UTP to connect the NetworkManager for Netcode for GameObjects (NGO), we need to provide the Allocation info without manually binding to it.
* In actual use, if you are using NGO for your game's networking, you would not also use the RelayUtpSetupHost/RelayUtpSetupClient at all, since their direct data transmission would be unnecessary.
* We keep both versions for this sample to demonstrate how each is set up, whether you want to just use Lobby + Relay or use NGO as well.
*/
/// <summary>
/// Host logic: Request a new Allocation, and then pass its info to the UTP adapter for NGO.
/// </summary>
public class RelayUtpNGOSetupHost : MonoBehaviour // If this is a MonoBehaviour, it can be added to the InGameRunner object for easier cleanup on game end.
{
private inGame.SetupInGame m_setupInGame;
private LocalLobby m_localLobby;
private Action m_onJoin;
public void Initialize(inGame.SetupInGame setupInGame, LocalLobby lobby, Action onJoin)
{
m_setupInGame = setupInGame;
m_localLobby = lobby;
m_onJoin = onJoin;
RelayAPIInterface.AllocateAsync(m_localLobby.MaxPlayerCount, OnAllocation);
}
private void OnAllocation(Allocation allocation)
{
RelayAPIInterface.GetJoinCodeAsync(allocation.AllocationId, OnRelayCode);
bool isSecure = false;
var endpoint = RelayUtpSetup.GetEndpointForAllocation(allocation.ServerEndpoints, allocation.RelayServer.IpV4, allocation.RelayServer.Port, out isSecure);
m_setupInGame.SetRelayServerData(RelayUtpSetup.AddressFromEndpoint(endpoint), endpoint.Port, allocation.AllocationIdBytes, allocation.Key, allocation.ConnectionData, allocation.ConnectionData, isSecure);
m_onJoin?.Invoke();
}
private void OnRelayCode(string relayCode)
{
m_localLobby.RelayNGOCode = relayCode;
}
}
/// <summary>
/// Client logic: Wait to receive the Relay code for NGO, and then pass the allocation info to the UTP adapter.
/// </summary>
public class RelayUtpNGOSetupClient : MonoBehaviour // This is also a MonoBehaviour for access to OnDestroy, to ensure unsubscription from the local lobby on game end.
{
private inGame.SetupInGame m_setupInGame;
private LocalLobby m_localLobby;
private Action m_onJoin;
public void Initialize(inGame.SetupInGame setupInGame, LocalLobby lobby, Action onJoin)
{
m_setupInGame = setupInGame;
m_localLobby = lobby;
m_onJoin = onJoin;
m_localLobby.onChanged += OnLobbyChange;
}
public void OnDestroy()
{
m_localLobby.onChanged -= OnLobbyChange;
}
private void OnLobbyChange(LocalLobby lobby)
{
if (m_localLobby.RelayNGOCode != null)
{
RelayAPIInterface.JoinAsync(m_localLobby.RelayNGOCode, OnJoin);
m_localLobby.onChanged -= OnLobbyChange;
}
}
private void OnJoin(JoinAllocation joinAllocation)
{
if (joinAllocation == null || this == null) // The returned JoinAllocation is null if allocation failed. this would be destroyed already if you quit the lobby while Relay is connecting.
return;
bool isSecure = false;
var endpoint = RelayUtpSetup.GetEndpointForAllocation(joinAllocation.ServerEndpoints, joinAllocation.RelayServer.IpV4, joinAllocation.RelayServer.Port, out isSecure);
m_setupInGame.SetRelayServerData(RelayUtpSetup.AddressFromEndpoint(endpoint), endpoint.Port, joinAllocation.AllocationIdBytes, joinAllocation.Key, joinAllocation.ConnectionData, joinAllocation.HostConnectionData, isSecure);
m_onJoin?.Invoke();
}
}
}

11
Assets/Scripts/Game/InGame/RelayNGOUtpSetup.cs.meta


fileFormatVersion: 2
guid: 90f27286cd4428d4c8487405d4141891
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存