浏览代码

WIP: Torn out LobbyUserObserver and LocalobbyObserver.

At least getting local Lobby Changes.
/main/staging/2021_Upgrade/Async_Refactor
当前提交
f73d89e6
共有 32 个文件被更改,包括 258 次插入257 次删除
  1. 54
      Assets/Prefabs/UI/UserCardPanel.prefab
  2. 17
      Assets/Scenes/mainScene.unity
  3. 214
      Assets/Scripts/GameLobby/Game/GameManager.cs
  4. 11
      Assets/Scripts/GameLobby/Game/LocalLobby.cs
  5. 2
      Assets/Scripts/GameLobby/Game/LocalLobbyList.cs
  6. 9
      Assets/Scripts/GameLobby/Game/LocalPlayer.cs
  7. 4
      Assets/Scripts/GameLobby/Infrastructure/Actionvalue.cs
  8. 1
      Assets/Scripts/GameLobby/Lobby/LobbyManager.cs
  9. 4
      Assets/Scripts/GameLobby/Lobby/LobbySynchronizer.cs
  10. 19
      Assets/Scripts/GameLobby/NGO/SetupInGame.cs
  11. 15
      Assets/Scripts/GameLobby/Relay/RelayUtpClient.cs
  12. 14
      Assets/Scripts/GameLobby/Relay/RelayUtpHost.cs
  13. 16
      Assets/Scripts/GameLobby/Relay/RelayUtpSetup.cs
  14. 4
      Assets/Scripts/GameLobby/Tests/Editor/MessengerTests.cs
  15. 6
      Assets/Scripts/GameLobby/UI/BackButtonUI.cs
  16. 4
      Assets/Scripts/GameLobby/UI/CreateMenuUI.cs
  17. 5
      Assets/Scripts/GameLobby/UI/EmoteButtonUI.cs
  18. 6
      Assets/Scripts/GameLobby/UI/EndGameButtonUI.cs
  19. 2
      Assets/Scripts/GameLobby/UI/GameStateVisibilityUI.cs
  20. 11
      Assets/Scripts/GameLobby/UI/JoinMenuUI.cs
  21. 21
      Assets/Scripts/GameLobby/UI/LobbyButtonUI.cs
  22. 2
      Assets/Scripts/GameLobby/UI/NameChangeUI.cs
  23. 4
      Assets/Scripts/GameLobby/UI/ReadyCheckUI.cs
  24. 4
      Assets/Scripts/GameLobby/UI/ShowWhenLobbyStateUI.cs
  25. 6
      Assets/Scripts/GameLobby/UI/StartLobbyButtonUI.cs
  26. 2
      Assets/Scripts/GameLobby/UI/UserNameUI.cs
  27. 2
      Assets/Scripts/GameLobby/UI/UserStateVisibilityUI.cs
  28. 18
      ProjectSettings/ProjectSettings.asset
  29. 11
      Assets/Scripts/GameLobby/Game/LobbyUserObserver.cs.meta
  30. 11
      Assets/Scripts/GameLobby/Game/LocalLobbyObserver.cs.meta
  31. 8
      Assets/Scripts/GameLobby/Game/LobbyUserObserver.cs
  32. 8
      Assets/Scripts/GameLobby/Game/LocalLobbyObserver.cs

54
Assets/Prefabs/UI/UserCardPanel.prefab


m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 5259773757747180216}
m_Father: {fileID: 4798292317257423901}

m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 2130654709780603783}
- {fileID: 2263383039778102024}

m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 2679964701276034275}
m_Father: {fileID: 3229036008637484624}

- component: {fileID: 1520530101828604145}
- component: {fileID: 6727759267638039682}
- component: {fileID: 5235189765028238254}
- component: {fileID: 788426075660952210}
- component: {fileID: 7885056472121154813}
- component: {fileID: 4826507163535553981}
m_Layer: 5

m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 2599817509811505645}
- {fileID: 5804120253616419419}

- {fileID: 21300000, guid: f18a89c12a346a8488ed507a0bd79d2e, type: 3}
- {fileID: 21300000, guid: 0fca28892f34375439c32b1ee1c8d655, type: 3}
m_vivoxUserHandler: {fileID: 4826507163535553981}
--- !u!114 &788426075660952210
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1767503274657767312}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a03b37d5b8df06948b36dfbc430a1ea5, type: 3}
m_Name:
m_EditorClassIdentifier:
OnObservedUpdated:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 5235189765028238254}
m_TargetAssemblyTypeName: LobbyRooms.UI.PlayerCardUI, LobbyRooms
m_MethodName: ObservedUpdated
m_Mode: 0
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!114 &7885056472121154813
MonoBehaviour:
m_ObjectHideFlags: 0

m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 5144918951328900891}
m_Father: {fileID: 3229036008637484624}

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 693969737454053021}
m_RootOrder: 0

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 4798292317257423901}
m_Father: {fileID: 3081577339344251787}

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4798292317257423901}
m_RootOrder: 1

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1122323841334202136}
- {fileID: 853418489715471536}

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5804120253616419419}
m_RootOrder: 1

m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 38.8
m_fontSize: 26
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5804120253616419419}
m_RootOrder: 0

m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6576240096323944936}
m_Father: {fileID: 3229036008637484624}

m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 693969737454053021}
m_Father: {fileID: 3229036008637484624}

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 814149882275566360}
m_RootOrder: 0

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8775333608543036802}
- {fileID: 131896552161369554}

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 131896552161369554}
m_RootOrder: 0

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2599817509811505645}
m_RootOrder: 0

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7829259871691718144}
m_Father: {fileID: 693969737454053021}

m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7160561887711141280}
m_Father: {fileID: 3229036008637484624}

m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7147564553318460541}
m_RootOrder: 0

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6125340877524701612}
m_Father: {fileID: 693969737454053021}

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1122323841334202136}
m_RootOrder: 0

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4798292317257423901}
m_RootOrder: 2

m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2889154384621986752}
m_RootOrder: 0

17
Assets/Scenes/mainScene.unity


objectReference: {fileID: 0}
- target: {fileID: 1282422528845055840, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0.0000015571713
value: -0.000003829884
value: 0.0000036023557
value: -0.00002864438
objectReference: {fileID: 0}
- target: {fileID: 1386321973193631240, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
propertyPath: m_AnchorMax.x

propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8354389055559135511, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
propertyPath: m_Alpha
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8354389055559135511, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
propertyPath: m_Interactable
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8354389055559135511, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
propertyPath: m_BlocksRaycasts
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8426100386232923098, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
propertyPath: m_AnchorMax.y
value: 0

m_RemovedComponents:
- {fileID: 3143918963127177442, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
- {fileID: 6900625576974141932, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
- {fileID: 7383922579991741677, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
m_SourcePrefab: {fileID: 100100000, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}

214
Assets/Scripts/GameLobby/Game/GameManager.cs


/// All the Data that is important gets updated in here, the GameManager in the mainScene has all the references
/// needed to run the game.
/// </summary>
public class GameManager : MonoBehaviour, IReceiveMessages
public class GameManager : MonoBehaviour
public LocalLobby LocalLobby => m_LocalLobby;
public Action<GameState> onGameStateChanged;

m_lobbyColorFilter = (LobbyColor)color;
}
public async Task CreateLobby(string name, bool isPrivate, int maxPlayers = 4)
public async Task<LocalPlayer> AwaitLocalUserInitialization()
{
while (m_LocalUser == null)
await Task.Delay(100);
return m_LocalUser;
}
public async void CreateLobby(string name, bool isPrivate, int maxPlayers = 4)
{
var lobby = await LobbyManager.CreateLobbyAsync(
name,

LobbyConverters.RemoteToLocal(lobby, m_LocalLobby);
}
catch(Exception exception)
catch (Exception exception)
{
Debug.LogError(exception);
}

}
}
/// <summary>
/// The Messaging System handles most of the core Lobby Service calls, and catches the callbacks from those calls.
/// These In turn update the observed variables and propagates the events to the game.
/// When looking for the interactions, look up the MessageType and search for it in the code to see where it is used outside this script.
/// EG. Locator.Get.Messenger.OnReceiveMessage(MessageType.RenameRequest, name);
/// </summary>
public async void OnReceiveMessage(MessageType type, object msg)
public async void JoinLobby(LocalLobby lobbyInfo)
if (type == MessageType.JoinLobbyRequest)
var lobby = await LobbyManager.JoinLobbyAsync(lobbyInfo.LobbyID.Value, lobbyInfo.LobbyCode.Value,
m_LocalUser);
if (lobby != null)
LocalLobby lobbyInfo = (LocalLobby)msg;
var lobby = await LobbyManager.JoinLobbyAsync(lobbyInfo.LobbyID.Value, lobbyInfo.LobbyCode.Value,
m_LocalUser);
if (lobby != null)
{
LobbyConverters.RemoteToLocal(lobby, m_LocalLobby);
JoinLobby();
}
else
{
SetGameState(GameState.JoinMenu);
}
LobbyConverters.RemoteToLocal(lobby, m_LocalLobby);
JoinLobby();
else if (type == MessageType.QueryLobbies)
else
LobbyList.QueryState.Value = LobbyQueryState.Fetching;
var qr = await LobbyManager.RetrieveLobbyListAsync(m_lobbyColorFilter);
SetGameState(GameState.JoinMenu);
}
}
public async void QueryLobbies()
{
LobbyList.QueryState.Value = LobbyQueryState.Fetching;
var qr = await LobbyManager.RetrieveLobbyListAsync(m_lobbyColorFilter);
if (qr != null)
SetCurrentLobbies(LobbyConverters.QueryToLocalList(qr));
else
LobbyList.QueryState.Value = LobbyQueryState.Error;
}
if (qr != null)
SetCurrentLobbies(LobbyConverters.QueryToLocalList(qr));
else
LobbyList.QueryState.Value = LobbyQueryState.Error;
}
else if (type == MessageType.QuickJoin)
{
var lobby = await LobbyManager.QuickJoinLobbyAsync(m_LocalUser, m_lobbyColorFilter);
if (lobby != null)
{
LobbyConverters.RemoteToLocal(lobby, m_LocalLobby);
JoinLobby();
}
else
{
SetGameState(GameState.JoinMenu);
}
}
else if (type == MessageType.RenameRequest)
{
string name = (string)msg;
if (string.IsNullOrWhiteSpace(name))
{
Locator.Get.Messenger.OnReceiveMessage(MessageType.DisplayErrorPopup,
"Empty Name not allowed."); // Lobby error type, then HTTP error type.
return;
}
m_LocalUser.DisplayName.Value = (string)msg;
}
else if (type == MessageType.UserSetEmote)
{
EmoteType emote = (EmoteType)msg;
m_LocalUser.Emote.Value = emote;
}
else if (type == MessageType.LobbyUserStatus)
public async void QuickJoin()
{
var lobby = await LobbyManager.QuickJoinLobbyAsync(m_LocalUser, m_lobbyColorFilter);
if (lobby != null)
m_LocalUser.UserStatus.Value = (UserStatus)msg;
}
else if (type == MessageType.CompleteCountdown)
{
//Start game for everyone
if (m_RelayClient is RelayUtpHost)
(m_RelayClient as RelayUtpHost).SendInGameState();
LobbyConverters.RemoteToLocal(lobby, m_LocalLobby);
JoinLobby();
else if (type == MessageType.ChangeMenuState)
else
SetGameState((GameState)msg);
SetGameState(GameState.JoinMenu);
else if (type == MessageType.ConfirmInGameState) { }
else if (type == MessageType.EndGame)
}
public void SetLocalUserName(string name)
{
if (string.IsNullOrWhiteSpace(name))
m_LocalLobby.LocalLobbyState.Value = LobbyState.Lobby;
SetUserLobbyState();
Locator.Get.Messenger.OnReceiveMessage(MessageType.DisplayErrorPopup,
"Empty Name not allowed."); // Lobby error type, then HTTP error type.
return;
m_LocalUser.DisplayName.Value = name;
}
public void SetLocalUserEmote(EmoteType emote)
{
SetUserEmote(m_LocalUser.ID.Value, emote);
}
public void SetUserEmote(string playerID, EmoteType emote)
{
var player = GetPlayerByID(playerID);
if (player == null)
return;
player.Emote.Value = emote;
}
public void SetLocalUserStatus(UserStatus status)
{
SetUserStatus(m_LocalUser.ID.Value, status);
}
public void SetUserStatus(string playerID, UserStatus status)
{
var player = GetPlayerByID(playerID);
if (player == null)
return;
m_LocalUser.UserStatus.Value = status;
}
public void CompleteCountDown()
{
//Start game for everyone
if (m_RelayClient is RelayUtpHost)
(m_RelayClient as RelayUtpHost).SendInGameState();
}
public void ChangeMenuState(GameState state)
{
SetGameState(state);
if (m_setupInGame)
m_setupInGame.OnGameEnd();
}
public void ConfirmIngameState()
{
m_setupInGame.ConfirmInGameState();
}
public void EndGame()
{
m_LocalLobby.LocalLobbyState.Value = LobbyState.Lobby;
LocalUserToLobby();
}
public void BeginCountdown()

await InitializeServices();
AuthenticatePlayer();
StartVivoxLogin();
Locator.Get.Messenger.Subscribe(this);
}
async Task InitializeServices()

#endif
await Auth.Authenticate(serviceProfileName);
}
void AuthenticatePlayer()
{

m_LocalLobby.AddPlayer(m_LocalUser); // The local LocalPlayer object will be hooked into UI
}
public async Task<LocalPlayer> LocalUserInitialized()
#endregion
LocalPlayer GetPlayerByID(string playerID)
while (m_LocalUser == null)
await Task.Delay(100);
return m_LocalUser;
if (m_LocalUser.ID.Value == playerID)
return m_LocalUser;
if (!m_LocalLobby.LocalPlayers.ContainsKey(playerID))
{
Debug.LogError($"No player by id : {playerID} in Local Lobby");
return null;
}
return m_LocalLobby.LocalPlayers[playerID];
#endregion
LocalGameState == GameState.Lobby;
LocalGameState == GameState.Lobby;
LocalGameState = state;
Debug.Log($"Switching Game State to : {LocalGameState}");
if (isLeavingLobby)

void CreateLobby()
{
Debug.Log("Creating Lobby");
m_LocalUser.IsHost.Value = true;
JoinLobby();
}

Debug.Log("Joining Lobby");
SetUserLobbyState();
LocalUserToLobby();
StartVivoxJoin();
}

}
m_RelayClient = client;
OnReceiveMessage(MessageType.LobbyUserStatus, UserStatus.Lobby);
SetUserStatus(m_LocalUser.ID.Value, UserStatus.Lobby);
}
}

doConnection?.Invoke();
}
void SetUserLobbyState()
void LocalUserToLobby()
OnReceiveMessage(MessageType.LobbyUserStatus, UserStatus.Lobby);
SetUserStatus(m_LocalUser.ID.Value, UserStatus.Lobby);
}
void ResetLocalLobby()

void ForceLeaveAttempt()
{
Locator.Get.Messenger.Unsubscribe(this);
if (!string.IsNullOrEmpty(m_LocalLobby?.LobbyID.Value))
{
#pragma warning disable 4014

11
Assets/Scripts/GameLobby/Game/LocalLobby.cs


/// (The way that the Lobby service handles its data doesn't necessarily match our needs, so we need to map from that to this LocalLobby for use in the sample code.)
/// </summary>
[System.Serializable]
public class LocalLobby : Observed<LocalLobby>
public class LocalLobby
{
public bool CanSetChanged = true;

m_LocalPlayers.Clear();
LobbyName.Value = "";
LobbyID.Value = "";
LobbyCode.Value = "";
Private.Value = false;

return sb.ToString();
}
// This ends up being called from the lobby list when we get data about a lobby without having joined it yet.
public override void CopyObserved(LocalLobby oldObserved)
{
// CopyObserved(oldObserved.Data, oldObserved.m_LocalPlayers);
}
}
}

2
Assets/Scripts/GameLobby/Game/LocalLobbyList.cs


[System.Serializable]
public class LocalLobbyList
{
LobbyQueryState m_CurrentState = LobbyQueryState.Empty;
public CallbackValue<LobbyQueryState> QueryState = new CallbackValue<LobbyQueryState>();
public Action<Dictionary<string, LocalLobby>> onLobbyListChange;

9
Assets/Scripts/GameLobby/Game/LocalPlayer.cs


/// Data for a local player instance. This will update data and is observed to know when to push local player changes to the entire lobby.
/// </summary>
[Serializable]
public class LocalPlayer : Observed<LocalPlayer>
public class LocalPlayer
{
public CallbackValue<bool> IsHost = new CallbackValue<bool>(false);
public CallbackValue<string> DisplayName = new CallbackValue<string>("");

Emote.Value = EmoteType.None;
UserStatus.Value = LobbyRelaySample.UserStatus.Menu;
}
public override void CopyObserved(LocalPlayer observed)
{
OnChanged(this);
}
}
}

4
Assets/Scripts/GameLobby/Infrastructure/Actionvalue.cs


{
m_CachedValue = cachedValue;
}
if (m_CachedValue.Equals(value))
if (m_CachedValue!=null&&m_CachedValue.Equals(value))
return;
m_CachedValue = value;
onChanged?.Invoke(m_CachedValue);

1
Assets/Scripts/GameLobby/Lobby/LobbyManager.cs


public void Dispose()
{
m_CurrentLobby = null;
m_HeartBeatTask.Dispose();
}
#region HeartBeat

4
Assets/Scripts/GameLobby/Lobby/LobbySynchronizer.cs


Locator.Get.Messenger.OnReceiveMessage(MessageType.DisplayErrorPopup,
"Host left the lobby! Disconnecting...");
Locator.Get.Messenger.OnReceiveMessage(MessageType.EndGame, null);
Locator.Get.Messenger.OnReceiveMessage(MessageType.ChangeMenuState, GameState.JoinMenu);
GameManager.Instance.ChangeMenuState(GameState.JoinMenu);
}
public void OnLobbyIdChanged(string lobbyID)

EndSynch();
}
}
}
}

19
Assets/Scripts/GameLobby/NGO/SetupInGame.cs


#pragma warning restore 4014
}
public void ConfirmInGameState()
{
}
if (type == MessageType.ConfirmInGameState) { }
else if (type == MessageType.MinigameBeginning)
if (type == MessageType.MinigameBeginning)
{
if (!m_hasConnectedViaNGO)
{

}
}
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();
}
private void OnGameEnd()
public void OnGameEnd()
{
if (m_doesNeedCleanup)
{

}
}
}
}
}

15
Assets/Scripts/GameLobby/Relay/RelayUtpClient.cs


{
m_localUser = localUser;
m_localLobby = localLobby;
m_localUser.onChanged += OnLocalChange;
//m_localUser.onChanged += OnLocalChange;
m_networkDriver = networkDriver;
m_connections = connections;
Locator.Get.UpdateSlow.Subscribe(UpdateSlow, k_heartbeatPeriod);

m_localUser.onChanged -= OnLocalChange;
//m_localUser.onChanged -= OnLocalChange;
Leave();
Locator.Get.UpdateSlow.Unsubscribe(UpdateSlow);
// Don't clean up the NetworkDriver here, or else our disconnect message won't get through to the host. The host will handle cleaning up the connection.

m_localLobby.LocalPlayers[id].UserStatus.Value = status;
}
else if (msgType == MsgType.StartCountdown)
Locator.Get.Messenger.OnReceiveMessage(MessageType.StartCountdown, null);
GameManager.Instance.BeginCountdown();
Locator.Get.Messenger.OnReceiveMessage(MessageType.CancelCountdown, null);
GameManager.Instance.CancelCountDown();
Locator.Get.Messenger.OnReceiveMessage(MessageType.ConfirmInGameState, null);
GameManager.Instance.ConfirmIngameState();
Locator.Get.Messenger.OnReceiveMessage(MessageType.EndGame, null);
GameManager.Instance.EndGame();
ProcessNetworkEventDataAdditional(conn, msgType, id);
}

Debug.LogError(msg);
Locator.Get.Messenger.OnReceiveMessage(MessageType.DisplayErrorPopup, msg);
Leave();
Locator.Get.Messenger.OnReceiveMessage(MessageType.ChangeMenuState, GameState.JoinMenu);
GameManager.Instance.ChangeMenuState(GameState.JoinMenu);
}
/// <summary>

/// </summary>
private void DoUserUpdate(NetworkDriver driver, NetworkConnection connection, LocalPlayer user)
{
}
/// <summary>

14
Assets/Scripts/GameLobby/Relay/RelayUtpHost.cs


// We rely on the PlayerDisconnect message instead of this disconnect message since this message might not arrive for a long time after the disconnect actually occurs.
}
public void OnUserStatusChanged()
{
CheckIfAllUsersReady();
}
if (type == MessageType.LobbyUserStatus)
CheckIfAllUsersReady();
else if (type == MessageType.EndGame
if (type == MessageType.EndGame
) // This assumes that only the host will have the End Game button available; otherwise, clients need to be able to send this message, too.
{
foreach (NetworkConnection connection in m_connections)

/// </summary>
public void SendInGameState()
{
Locator.Get.Messenger.OnReceiveMessage(MessageType.ConfirmInGameState, null);
GameManager.Instance.ConfirmIngameState();
foreach (NetworkConnection connection in m_connections)
WriteByte(m_networkDriver, connection, m_localUser.ID.Value, MsgType.ConfirmInGame, 0);
}

m_localLobby.RelayServer = null;
}
}
}
}

16
Assets/Scripts/GameLobby/Relay/RelayUtpSetup.cs


protected override void JoinRelay()
{
m_localLobby.onChanged += OnLobbyChange;
m_localLobby.RelayCode.onChanged += OnRelayChanged;
private void OnLobbyChange(LocalLobby lobby)
private void OnRelayChanged(string relayCode)
if (m_localLobby.RelayCode != null)
{
RelayAPIInterface.JoinAsync(m_localLobby.RelayCode.Value, OnJoin);
m_localLobby.onChanged -= OnLobbyChange;
}
if (string.IsNullOrEmpty(relayCode))
return;
RelayAPIInterface.JoinAsync(m_localLobby.RelayCode.Value, OnJoin);
m_localLobby.RelayCode.onChanged -= OnRelayChanged;
}
private void OnJoin(JoinAllocation joinAllocation)

m_onJoinComplete(true, client);
var connectionInfo = $"{m_allocation.RelayServer.IpV4}:{m_allocation.RelayServer.Port}";
// await LobbyManager.Instance.UpdatePlayerRelayInfoAsync(m_allocation.AllocationId.ToString(), m_localLobby.RelayCode,connectionInfo);
await GameManager.Instance.LobbyManager.UpdatePlayerRelayInfoAsync(m_allocation.AllocationId.ToString(), m_localLobby.RelayCode.Value,connectionInfo);
}
}
}

4
Assets/Scripts/GameLobby/Tests/Editor/MessengerTests.cs


{
public class MessengerTests
{
#region Test classes
/*#region Test classes
/// <summary>Trivial message recipient that will run some action on any message.</summary>
class Subscriber : IReceiveMessages
{

messenger.OnReceiveMessage(MessageType.None, null);
Assert.AreEqual(1, msgCount, "Should have acted on the message.");
}
}*/
}
}

6
Assets/Scripts/GameLobby/UI/BackButtonUI.cs


/// <summary>
/// For navigating the main menu.
/// </summary>
public class BackButtonUI : MonoBehaviour
public class BackButtonUI : UIPanelBase
Locator.Get.Messenger.OnReceiveMessage(MessageType.ChangeMenuState, GameState.JoinMenu);
Manager.ChangeMenuState(GameState.JoinMenu);
Locator.Get.Messenger.OnReceiveMessage(MessageType.ChangeMenuState, GameState.Menu);
Manager.ChangeMenuState(GameState.Menu);
}
}
}

4
Assets/Scripts/GameLobby/UI/CreateMenuUI.cs


public void OnCreatePressed()
{
//Disabled as it's a one-off butto call
#pragma warning disable 4014
GameManager.Instance.CreateLobby(m_ServerName, m_IsServerPrivate);
#pragma warning restore 4014
Manager.CreateLobby(m_ServerName, m_IsServerPrivate);
}
}
}

5
Assets/Scripts/GameLobby/UI/EmoteButtonUI.cs


using TMPro;
using UnityEditor.Scripting;
using UnityEngine;
namespace LobbyRelaySample.UI

/// </summary>
public class EmoteButtonUI : MonoBehaviour
public class EmoteButtonUI : UIPanelBase
{
[SerializeField]
EmoteType m_emoteType;

Locator.Get.Messenger.OnReceiveMessage(MessageType.UserSetEmote, m_emoteType);
Manager.SetLocalUserEmote(m_emoteType);
}
}
}

6
Assets/Scripts/GameLobby/UI/EndGameButtonUI.cs


using UnityEngine;
public class EndGameButtonUI : MonoBehaviour
public class EndGameButtonUI : UIPanelBase
Locator.Get.Messenger.OnReceiveMessage(MessageType.EndGame, null);
Manager.EndGame();
}
}
}

2
Assets/Scripts/GameLobby/UI/GameStateVisibilityUI.cs


Hide();
else
Show();
Debug.Log($"GameStateChanged for {gameObject.name} : {state}");
}
public override void Start()

11
Assets/Scripts/GameLobby/UI/JoinMenuUI.cs


public void OnJoinButtonPressed()
{
Locator.Get.Messenger.OnReceiveMessage(MessageType.JoinLobbyRequest, m_LocalLobbySelected);
Manager.JoinLobby(m_LocalLobbySelected);
Locator.Get.Messenger.OnReceiveMessage(MessageType.QueryLobbies, null);
Manager.QueryLobbies();
}
void OnLobbyListChanged(Dictionary<string, LocalLobby> lobbyList)

public void OnQuickJoin()
{
Locator.Get.Messenger.OnReceiveMessage(MessageType.QuickJoin, null);
Manager.QuickJoin();
}
bool CanDisplay(LocalLobby lobby)

void AddNewLobbyButton(string lobbyCode, LocalLobby lobby)
{
var lobbyButtonInstance = Instantiate(m_LobbyButtonPrefab, m_LobbyButtonParent);
lobbyButtonInstance.GetComponent<LocalLobbyObserver>().BeginObserving(lobby);
lobby.onDestroyed += RemoveLobbyButton; // Set up to clean itself
lobbyButtonInstance.onLobbyPressed.AddListener(LobbyButtonSelected);
m_LobbyButtons.Add(lobbyCode, lobbyButtonInstance);
m_LocalLobby.Add(lobbyCode, lobby);

{
var lobbyID = lobby.LobbyID.Value;
var lobbyButton = m_LobbyButtons[lobbyID];
lobbyButton.GetComponent<LocalLobbyObserver>().EndObserving();
}
}

21
Assets/Scripts/GameLobby/UI/LobbyButtonUI.cs


using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.Events;

/// Subscribed to on instantiation to pass our lobby data back
/// </summary>
public UnityEvent<LocalLobby> onLobbyPressed;
LocalLobbyObserver m_DataObserver;
LocalLobby m_Lobby;
/// <summary>

{
//TODO Select Lobby
onLobbyPressed.Invoke(m_Lobby);
SetLobbyname(m_Lobby.LobbyName.Value);
SetLobbyCount(m_Lobby.LocalPlayers);
m_Lobby.LobbyName.onChanged += SetLobbyname;
m_Lobby.onUserListChanged += SetLobbyCount;
}
void SetLobbyname(string lobbyName)
{
lobbyCountText.SetText($"{m_Lobby.PlayerCount}/{m_Lobby.MaxPlayerCount}");
}
void SetLobbyCount(Dictionary<string, LocalPlayer> userList)
{
lobbyCountText.SetText($"{userList.Count}/{m_Lobby.MaxPlayerCount}");
}
}

2
Assets/Scripts/GameLobby/UI/NameChangeUI.cs


{
public void OnEndNameEdit(string name)
{
Locator.Get.Messenger.OnReceiveMessage(MessageType.RenameRequest, name);
Manager.SetLocalUserName(name);
}
}
}

4
Assets/Scripts/GameLobby/UI/ReadyCheckUI.cs


/// <summary>
/// Button callbacks for the "Ready"/"Not Ready" buttons used to indicate the local player is ready/not ready.
/// </summary>
public class ReadyCheckUI : MonoBehaviour
public class ReadyCheckUI : UIPanelBase
{
public void OnReadyButton()
{

}
void ChangeState(UserStatus status)
{
Locator.Get.Messenger.OnReceiveMessage(MessageType.LobbyUserStatus, status);
Manager.SetLocalUserStatus(status);
}
}
}

4
Assets/Scripts/GameLobby/UI/ShowWhenLobbyStateUI.cs


public void OnDestroy()
{
if (GameManager.Instance == null)
if (Manager== null)
}
}

6
Assets/Scripts/GameLobby/UI/StartLobbyButtonUI.cs


using UnityEngine;
using LobbyRelaySample.UI;
namespace LobbyRelaySample
{

public class StartLobbyButtonUI : MonoBehaviour
public class StartLobbyButtonUI : UIPanelBase
Locator.Get.Messenger.OnReceiveMessage(MessageType.ChangeMenuState, GameState.JoinMenu);
Manager.ChangeMenuState(GameState.JoinMenu);
}
}
}

2
Assets/Scripts/GameLobby/UI/UserNameUI.cs


public override async void Start()
{
base.Start();
var localUser = await GameManager.Instance.LocalUserInitialized();
var localUser = await GameManager.Instance.AwaitLocalUserInitialization();
localUser.DisplayName.onChanged += SetText;
}

2
Assets/Scripts/GameLobby/UI/UserStateVisibilityUI.cs


public override async void Start()
{
base.Start();
var localUser = await Manager.LocalUserInitialized();
var localUser = await Manager.AwaitLocalUserInitialization();
localUser.IsHost.onChanged += OnUserHostChanged;
localUser.UserStatus.onChanged += OnUserStatusChanged;

18
ProjectSettings/ProjectSettings.asset


--- !u!129 &1
PlayerSettings:
m_ObjectHideFlags: 0
serializedVersion: 22
serializedVersion: 23
productGUID: 5cdb00278111a2a4885ff1a3fcb6c043
AndroidProfiler: 0
AndroidFilterTouchesWhenObscured: 0

iOSLaunchScreeniPadCustomStoryboardPath:
iOSDeviceRequirements: []
iOSURLSchemes: []
macOSURLSchemes: []
iOSBackgroundModes: 0
iOSMetalForceHardShadows: 0
metalEditorSupport: 1

m_BuildTargetGraphicsJobMode: []
m_BuildTargetGraphicsAPIs:
- m_BuildTarget: AndroidPlayer
m_APIs: 150000000b000000
m_Automatic: 1
m_APIs: 0b00000008000000
m_Automatic: 0
- m_BuildTarget: iOSSupport
m_APIs: 10000000
m_Automatic: 1

m_BuildTargetGroupLightmapEncodingQuality: []
m_BuildTargetGroupLightmapSettings: []
m_BuildTargetNormalMapEncoding: []
m_BuildTargetDefaultTextureCompressionFormat: []
playModeTestRunnerEnabled: 0
runPlayModeTestAsEditModeTest: 0
actionOnDotNetUnhandledException: 1

switchScreenResolutionBehavior: 2
switchUseCPUProfiler: 0
switchUseGOLDLinker: 0
switchLTOSetting: 0
switchApplicationID: 0x01004b9000490000
switchNSODependencies:
switchTitleNames_0:

switchPlayerConnectionEnabled: 1
switchUseNewStyleFilepaths: 0
switchUseMicroSleepForYield: 1
switchEnableRamDiskSupport: 0
switchRamDiskSpaceSize: 12
ps4NPAgeRating: 12
ps4NPTitleSecret:
ps4NPTrophyPackPath:

ps4videoRecordingFeaturesUsed: 0
ps4contentSearchFeaturesUsed: 0
ps4CompatibilityPS5: 0
ps4AllowPS5Detection: 0
ps4GPU800MHz: 1
ps4attribEyeToEyeDistanceSettingVR: 0
ps4IncludedModules: []

webGLThreadsSupport: 0
webGLDecompressionFallback: 0
scriptingDefineSymbols:
1:
Standalone: UGS_BETA_LOBBY_EVENTS;UGS_LOBBY_EVENTS
additionalCompilerArguments: {}
platformArchitecture: {}
scriptingBackend: {}

suppressCommonWarnings: 1
allowUnsafeCode: 0
useDeterministicCompilation: 1
useReferenceAssemblies: 1
enableRoslynAnalyzers: 1
additionalIl2CppArgs:
scriptingRuntimeVersion: 1

metroFTAName:
metroFTAFileTypes: []
metroProtocolName:
vcxProjDefaultLanguage:
XboxOneProductId:
XboxOneUpdateKey:
XboxOneSandboxId:

organizationId: operate-samples
cloudEnabled: 0
legacyClampBlendShapeWeights: 0
playerDataPath:
forceSRGBBlit: 1
virtualTexturingSupportEnabled: 0

11
Assets/Scripts/GameLobby/Game/LobbyUserObserver.cs.meta


fileFormatVersion: 2
guid: a03b37d5b8df06948b36dfbc430a1ea5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Assets/Scripts/GameLobby/Game/LocalLobbyObserver.cs.meta


fileFormatVersion: 2
guid: 70dfc2fde0a9ef04eaff29a138f0bf45
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Scripts/GameLobby/Game/LobbyUserObserver.cs


namespace LobbyRelaySample
{
/// <summary>
/// Holds a LocalPlayer value and notifies all subscribers when it has been changed.
/// Check the GameManager in the mainScene for the list of observers being used in the project.
/// </summary>
public class LobbyUserObserver : ObserverBehaviour<LocalPlayer> { }
}

8
Assets/Scripts/GameLobby/Game/LocalLobbyObserver.cs


namespace LobbyRelaySample
{
/// <summary>
/// Holds a LocalLobby value and notifies all subscribers when it has been changed.
/// Check the GameManager in the mainScene for the list of observers being used in the project.
/// </summary>
public class LocalLobbyObserver : ObserverBehaviour<LocalLobby> { }
}
正在加载...
取消
保存