浏览代码

saving Wire implementation before tearing it outw

/main/staging/wire_implementation
当前提交
dbb69d28
共有 37 个文件被更改,包括 866 次插入566 次删除
  1. 21
      Assets/Art/Glyph/Symbols.png.meta
  2. 9
      Assets/Art/Icons/ClickParticleMat.mat
  3. 7
      Assets/Prefabs/GameManager.prefab
  4. 189
      Assets/Prefabs/NGO/InGameLogic.prefab
  5. 13
      Assets/Prefabs/Runes/icon_particle.mat
  6. 21
      Assets/Renderer/glyphGameURP.asset
  7. 114
      Assets/Scenes/mainScene.unity
  8. 87
      Assets/Scripts/GameLobby/Game/GameManager.cs
  9. 2
      Assets/Scripts/GameLobby/Game/LocalLobby.cs
  10. 1
      Assets/Scripts/GameLobby/Infrastructure/LogHandlerSettings.cs
  11. 24
      Assets/Scripts/GameLobby/Lobby/LobbyAPIInterface.cs
  12. 310
      Assets/Scripts/GameLobby/Lobby/LobbyAsyncRequests.cs
  13. 15
      Assets/Scripts/GameLobby/Lobby/LobbyContentUpdater.cs
  14. 5
      Assets/Scripts/GameLobby/NGO/InGameRunner.cs
  15. 2
      Assets/Scripts/GameLobby/NGO/PlayerCursor.cs
  16. 25
      Assets/Scripts/GameLobby/NGO/SetupInGame.cs
  17. 14
      Assets/Scripts/GameLobby/NGO/SymbolContainer.cs
  18. 4
      Assets/Scripts/GameLobby/Relay/RelayAPIInterface.cs
  19. 19
      Assets/Scripts/GameLobby/Relay/RelayUtpHost.cs
  20. 19
      Assets/Scripts/GameLobby/Relay/RelayUtpSetup.cs
  21. 127
      Assets/Scripts/GameLobby/Tests/PlayMode/LobbyRoundtripTests.cs
  22. 8
      Assets/Scripts/GameLobby/UI/RateLimitVisibility.cs
  23. 14
      Packages/manifest.json
  24. 114
      Packages/packages-lock.json
  25. 9
      ProjectSettings/GraphicsSettings.asset
  26. 27
      ProjectSettings/PackageManagerSettings.asset
  27. 4
      ProjectSettings/ProjectVersion.txt
  28. 3
      ProjectSettings/QualitySettings.asset
  29. 2
      ProjectSettings/URPProjectSettings.asset
  30. 112
      Assets/Prefabs/NGO/NetworkManager.prefab
  31. 7
      Assets/Prefabs/NGO/NetworkManager.prefab.meta
  32. 27
      Assets/Scripts/GameLobby/Tests/PlayMode/AsyncTestHelper.cs
  33. 11
      Assets/Scripts/GameLobby/Tests/PlayMode/AsyncTestHelper.cs.meta
  34. 27
      Assets/UniversalRenderPipelineGlobalSettings.asset
  35. 8
      Assets/UniversalRenderPipelineGlobalSettings.asset.meta
  36. 15
      ProjectSettings/RiderScriptEditorPersistedState.asset
  37. 16
      ProjectSettings/ShaderGraphSettings.asset

21
Assets/Art/Glyph/Symbols.png.meta


streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMasterTextureLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0

edges: []
weights: []
secondaryTextures: []
nameFileIdTable:
17_elemental: -2657090017763772448
4_matter: -612294750349367285
5_gas: 4906567379933833492
7_star: 4588468031203458904
2_cold: -469525390435789673
entropy: 5531826651420068725
10_life: 6472110944188623208
9_planet: -5148847302637816175
13_mind: -2962330253262605572
16_evil: -5893568625793066583
1_heat: -3739395637988037281
15_good: -431797579490579562
0_gravity: 8720604468809159126
8_system: 4830219810074551288
6_water: 8796499958254778168
14_moon: -5670611702303752676
3_entanglement: -5196480314518052078
12_expansion: -5943722948072908530
11_radiation: -2449591561013552763
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0

9
Assets/Art/Icons/ClickParticleMat.mat


m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 4
version: 5
serializedVersion: 6
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}

m_ShaderKeywords: _ALPHATEST_ON
m_ValidKeywords:
- _ALPHATEST_ON
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0

m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AlphaClip: 1
- _Blend: 0

7
Assets/Prefabs/GameManager.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: []
m_Father: {fileID: 7716713811812636911}
m_RootOrder: 0

m_Script: {fileID: 11500000, guid: 3f7533ddeca587549a9798a65a8670ba, type: 3}
m_Name:
m_EditorClassIdentifier:
m_prefabNetworkManager: {fileID: 238192747445020667, guid: 73173c97c128d614aa2a1167a2eaea68, type: 3}
m_NetworkManagerPrefab: {fileID: 5021303663353436182, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
m_IngameRunnerPrefab: {fileID: 238192747445020667, guid: 73173c97c128d614aa2a1167a2eaea68, type: 3}
m_disableWhileInGame: []
--- !u!114 &5235782363599194820
MonoBehaviour:

m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 624.1824, y: 320.50745, z: -29748.68}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 802462301182945455}
m_Father: {fileID: 0}

m_Script: {fileID: 11500000, guid: b4f7225f73bfe6a4d9133ee45ac9cd73, type: 3}
m_Name:
m_EditorClassIdentifier:
m_GameStateObservers: []
m_LocalMenuStateObservers: []
m_LocalLobbyObservers: []
m_LocalUserObservers: []
m_LobbyServiceObservers: []

189
Assets/Prefabs/NGO/InGameLogic.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: []
m_Father: {fileID: 1250806127447164487}
m_RootOrder: 0

serializedVersion: 6
m_Component:
- component: {fileID: 485451675458297819}
- component: {fileID: 2273653745935453042}
- component: {fileID: 5378807363724719273}
m_Layer: 0
m_Name: InGameLogic
m_TagString: Untagged

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: 6532331214593598572}
- {fileID: 5289034077109495657}

m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2273653745935453042
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 238192747445020667}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 593a2fe42fa9d37498c96f9a383b6521, type: 3}
m_Name:
m_EditorClassIdentifier:
DontDestroy: 1
RunInBackground: 0
LogLevel: 1
NetworkConfig:
ProtocolVersion: 0
NetworkTransport: {fileID: 5378807363724719273}
PlayerPrefab: {fileID: 0}
NetworkPrefabs:
- Override: 0
Prefab: {fileID: 3227847727972158006, guid: 905594b4ee5bb864a84af916cc445d1b, type: 3}
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}
- Override: 0
Prefab: {fileID: 5240148789413552765, guid: f42ed38d10b57ec48870f76a7a63389e, type: 3}
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}
- Override: 0
Prefab: {fileID: 8828823320646980938, guid: e371ca3112f9e244ab574b472387b64b, type: 3}
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}
TickRate: 30
ClientConnectionBufferTimeout: 10
ConnectionApproval: 0
ConnectionData:
EnableTimeResync: 0
TimeResyncInterval: 30
EnsureNetworkVariableLengthSafety: 0
EnableSceneManagement: 1
ForceSamePrefabs: 1
RecycleNetworkIds: 1
NetworkIdRecycleDelay: 120
RpcHashSize: 0
LoadSceneTimeOut: 120
MessageBufferTimeout: 20
EnableNetworkLogs: 1
--- !u!114 &5378807363724719273
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 238192747445020667}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 6960e84d07fb87f47956e7a81d71c4e6, type: 3}
m_Name:
m_EditorClassIdentifier:
m_ProtocolType: 1
m_MaximumPacketSize: 1400
m_MaxPacketQueueSize: 512
m_SendQueueBatchSize: 6144
m_HeartbeatTimeoutMS: 500
m_ConnectTimeoutMS: 1000
m_MaxConnectAttempts: 60
m_DisconnectTimeoutMS: 30000
ConnectionData:
Address: 127.0.0.1
Port: 7777
--- !u!1 &413870477192997562
GameObject:
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: []
m_Father: {fileID: 9210454441405939118}
m_RootOrder: 0

m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 485451675458297819}
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: 4271018735512598272}
- {fileID: 5754962845139143862}

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: 5231970163014429165}
m_Father: {fileID: 3536358479196928666}

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: 3812834876162241050}
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: 2884208290717289317}
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: 1093042331837590349}
- {fileID: 5557516240847477329}

serializedVersion: 6
m_Component:
- component: {fileID: 5289034077109495657}
- component: {fileID: 8928417086886337167}
- component: {fileID: 6636000542315549800}
m_Layer: 0
m_Name: InGameRunner
m_TagString: Untagged

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
--- !u!114 &8928417086886337167
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1306704497370578788}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 951099334
AlwaysReplicateAsRoot: 0
DontDestroyWithOwner: 0
AutoObjectParentSync: 1
--- !u!114 &6673480979101889538
MonoBehaviour:
m_ObjectHideFlags: 0

serializedVersion: 2
m_Size: {x: 16, y: 120, z: 1}
m_Center: {x: 0, y: 60, z: 0}
--- !u!114 &6636000542315549800
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1306704497370578788}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 951099334
AlwaysReplicateAsRoot: 0
DontDestroyWithOwner: 0
AutoObjectParentSync: 1
--- !u!1 &1912141680601921478
GameObject:
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: 4683486642073920110}
m_Father: {fileID: 6730446115375840747}

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: 1061569962213594104}
m_RootOrder: 0

m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: -12, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 485451675458297819}
m_RootOrder: 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: 198237009240628586}
- {fileID: 16037789917111781}

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: 4905162368523321093}
m_Father: {fileID: 3719423043742445757}

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: 5754962845139143862}
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: []
m_Father: {fileID: 5754962845139143862}
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: 7180346621296967487}
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: 1061569962213594104}
- {fileID: 2124973746581900278}

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: 6347969710836929235}
m_Father: {fileID: 3536358479196928666}

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

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: 4784983905519642549}
m_RootOrder: 0

serializedVersion: 6
m_Component:
- component: {fileID: 8722147382518631401}
- component: {fileID: 2654986621618399364}
- component: {fileID: 4210703794441540767}
m_Layer: 5
m_Name: ResultsSequence

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: 6873234893560763838}
m_Father: {fileID: 8063659512749448051}

m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &2654986621618399364
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3687523182501472382}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 951099334
AlwaysReplicateAsRoot: 0
DontDestroyWithOwner: 0
AutoObjectParentSync: 1
--- !u!114 &4210703794441540767
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: 609939759751866630}
- {fileID: 8613470296925483228}

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: 3698041764509804342}
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: 2124973746581900278}
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: 1250806127447164487}
- {fileID: 669834599338486315}

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: 9208629700357753581}
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: 3374802268437532309}
m_Father: {fileID: 40575182689869500}

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: 8939277680710968141}
m_Father: {fileID: 3719423043742445757}

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: 762979378731227237}
m_Father: {fileID: 40575182689869500}

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: 1900156070638843258}
m_RootOrder: 0

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

m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 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: 3350915488537301533}
- {fileID: 5055996223209802668}

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: 4271018735512598272}
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: 9208629700357753581}
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: 3719423043742445757}
- {fileID: 40575182689869500}

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: 1093042331837590349}
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: 5557516240847477329}
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: 5557516240847477329}
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: []
m_Father: {fileID: 2124973746581900278}
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: 8984575746100710798}
m_Father: {fileID: 6730446115375840747}

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: 669834599338486315}
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: 7978301007878594822}
- {fileID: 7131533514903797874}

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: 7461186955731390703}
m_Father: {fileID: 8897506674002061787}

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: 5954072923278860053}
- {fileID: 7025050144556213061}

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: 3983867301106818349}
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: 6183038953491067537}
- {fileID: 6730446115375840747}

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: 2884208290717289317}
m_RootOrder: 3

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

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

m_PresetInfoIsWorld: 0
--- !u!95 &9205289577047239847
Animator:
serializedVersion: 3
serializedVersion: 4
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}

m_UpdateMode: 0
m_ApplyRootMotion: 0
m_LinearVelocityBlending: 0
m_StabilizeFeet: 0
m_WarningMessage:
m_HasTransformHierarchy: 1
m_AllowConstantClipSamplingOptimization: 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: 1061428408745274728}
m_Father: {fileID: 8897506674002061787}

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: 2884208290717289317}
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: 2884208290717289317}
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: 3698041764509804342}
- {fileID: 9208629700357753581}

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: 8262658662678090917}
m_Father: {fileID: 485451675458297819}

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: 2281109580131452863}
m_Father: {fileID: 6730446115375840747}

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: 5397289210807700292}
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.3, y: 1.3, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 9210454441405939118}
m_RootOrder: 3

13
Assets/Prefabs/Runes/icon_particle.mat


%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}

m_ShaderKeywords: _ALPHATEST_ON _COLORADDSUBDIFF_ON
m_ValidKeywords:
- _ALPHATEST_ON
- _COLORADDSUBDIFF_ON
- _SURFACE_TYPE_TRANSPARENT
m_InvalidKeywords:
- _FLIPBOOKBLENDING_OFF
m_LightmapFlags: 6
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0

disabledShaderPasses:
- SHADOWCASTER
- DepthOnly
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:

m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AlphaClip: 1
- _Blend: 0

m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 4
version: 5

21
Assets/Renderer/glyphGameURP.asset


m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3}
m_Name: glyphGameURP
m_EditorClassIdentifier:
k_AssetVersion: 5
k_AssetPreviousVersion: 5
k_AssetVersion: 9
k_AssetPreviousVersion: 9
m_RendererType: 1
m_RendererData: {fileID: 0}
m_RendererDataList:

m_RequireOpaqueTexture: 0
m_OpaqueDownsampling: 1
m_SupportsTerrainHoles: 1
m_StoreActionsOptimization: 0
m_UpscalingFilter: 0
m_FsrOverrideSharpness: 0
m_FsrSharpness: 0.92
m_MainLightRenderingMode: 1
m_MainLightShadowsSupported: 1
m_MainLightShadowmapResolution: 2048

m_AdditionalLightsShadowmapResolution: 512
m_AdditionalLightsShadowResolutionTierLow: 128
m_AdditionalLightsShadowResolutionTierMedium: 256
m_AdditionalLightsShadowResolutionTierHigh: 512
m_ReflectionProbeBlending: 0
m_ReflectionProbeBoxProjection: 0
m_CascadeBorder: 0.1
m_ConservativeEnclosingSphere: 0
m_NumIterationsEnclosingSphere: 64
m_AdditionalLightsCookieResolution: 2048
m_AdditionalLightsCookieFormat: 3
m_SupportsLightLayers: 0
m_UseFastSRGBLinearConversion: 0
m_ShadowType: 1
m_LocalShadowsSupported: 0
m_LocalShadowsAtlasResolution: 256

m_VolumeFrameworkUpdateMode: 0
m_ShadowCascades: 0

114
Assets/Scenes/mainScene.unity


m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0, y: 0, z: 0}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1853015250}
m_Father: {fileID: 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: 0}
m_RootOrder: 3

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

serializedVersion: 2
m_Bits: 1
m_VolumeTrigger: {fileID: 0}
m_VolumeFrameworkUpdateModeOption: 2
m_RenderPostProcessing: 0
m_Antialiasing: 0
m_AntialiasingQuality: 2

m_CorrespondingSourceObject: {fileID: 8628454958398271551, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
m_PrefabInstance: {fileID: 8628454959146822954}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &794646441
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 5481270937743757918, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
propertyPath: m_Name
value: NetworkManager
objectReference: {fileID: 0}
- target: {fileID: 5665493986528408842, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
propertyPath: m_RootOrder
value: 6
objectReference: {fileID: 0}
- target: {fileID: 5665493986528408842, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5665493986528408842, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
propertyPath: m_LocalPosition.y
value: 52.01943
objectReference: {fileID: 0}
- target: {fileID: 5665493986528408842, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
propertyPath: m_LocalPosition.z
value: -6
objectReference: {fileID: 0}
- target: {fileID: 5665493986528408842, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 5665493986528408842, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 5665493986528408842, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: 5665493986528408842, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 5665493986528408842, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5665493986528408842, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5665493986528408842, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: b963f71e4874d4066bc72b9224e3ffce, type: 3}
--- !u!114 &818919068 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 9110417292276624615, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}

propertyPath: m_popUp
value:
objectReference: {fileID: 2637199315837045700}
- target: {fileID: 8425041362224744845, guid: 35249394896e31643ba0641c2a6f8e8d, type: 3}
propertyPath: m_editorLogVerbosity
value: 2
objectReference: {fileID: 0}
- target: {fileID: 8425041362224744849, guid: 35249394896e31643ba0641c2a6f8e8d, type: 3}
propertyPath: m_Pivot.x
value: 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: 7866770}
m_RootOrder: 0

objectReference: {fileID: 0}
- target: {fileID: 2832906903618240629, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
propertyPath: m_AnchorMax.y
value: 0
value: 1
value: 0
value: 1
value: 0
value: 50
value: 0
value: 50
value: 0
value: 155.5
value: 0
value: -27.5
objectReference: {fileID: 0}
- target: {fileID: 2938110563166987729, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
propertyPath: m_AnchorMax.y

objectReference: {fileID: 0}
- target: {fileID: 6314503137265266719, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
propertyPath: m_AnchorMax.y
value: 0
value: 1
value: 0
value: 1
value: 0
value: 50
value: 0
value: 50
value: 0
value: 49.5
value: 0
value: -27.5
value: 0
value: 1
value: 0
value: 1
value: 0
value: 50
value: 0
value: 50
value: 0
value: 102.5
value: 0
value: -27.5
objectReference: {fileID: 0}
- target: {fileID: 6468178321825623330, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
propertyPath: m_AnchorMax.y

objectReference: {fileID: 0}
- target: {fileID: 7029771435095122102, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
propertyPath: m_AnchorMax.y
value: 0
value: 1
value: 0
value: 1
value: 0
value: 50
value: 0
value: 50
value: 0
value: 208.5
value: 0
value: -27.5
objectReference: {fileID: 0}
- target: {fileID: 7182908607506352373, guid: 9aae991127b410c45a001ecd7f75311d, type: 3}
propertyPath: m_AnchorMax.y

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


using System;
using System.Collections;
using System.Collections.Generic;
using LobbyRelaySample.lobby;
using UnityEngine;
using UnityEngine.Serialization;

/// 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 void OnReceiveMessage(MessageType type, object msg)
public async void OnReceiveMessage(MessageType type, object msg)
LobbyAsyncRequests.Instance.CreateLobbyAsync(createLobbyData.LobbyName, createLobbyData.MaxPlayerCount, createLobbyData.Private, m_localUser, (r) =>
{
lobby.LobbyConverters.RemoteToLocal(r, m_localLobby);
OnCreatedLobby();
},
OnFailedJoin);
var lobby = await LobbyAsyncRequests.Instance.CreateLobbyAsync(
createLobbyData.LobbyName,
createLobbyData.MaxPlayerCount,
createLobbyData.Private, m_localUser);
if (lobby != null)
{
LobbyConverters.RemoteToLocal(lobby, m_localLobby);
OnCreatedLobby();
}
else
{
OnFailedJoin();
}
LobbyAsyncRequests.Instance.JoinLobbyAsync(lobbyInfo.LobbyID, lobbyInfo.LobbyCode, m_localUser, (r) =>
{
lobby.LobbyConverters.RemoteToLocal(r, m_localLobby);
OnJoinedLobby();
},
OnFailedJoin);
var lobby = await LobbyAsyncRequests.Instance.JoinLobbyAsync(lobbyInfo.LobbyID, lobbyInfo.LobbyCode,
m_localUser);
if (lobby != null)
{
LobbyConverters.RemoteToLocal(lobby, m_localLobby);
OnJoinedLobby();
}
else
{
OnFailedJoin();
}
LobbyAsyncRequests.Instance.RetrieveLobbyListAsync(
qr =>
{
if (qr != null)
OnLobbiesQueried(lobby.LobbyConverters.QueryToLocalList(qr));
},
er =>
{
OnLobbyQueryFailed();
},
m_lobbyColorFilter);
var qr = await LobbyAsyncRequests.Instance.RetrieveLobbyListAsync(m_lobbyColorFilter);
if (qr != null)
OnLobbiesQueried(LobbyConverters.QueryToLocalList(qr));
else
OnLobbyQueryFailed();
LobbyAsyncRequests.Instance.QuickJoinLobbyAsync(m_localUser, m_lobbyColorFilter, (r) =>
{
lobby.LobbyConverters.RemoteToLocal(r, m_localLobby);
OnJoinedLobby();
},
OnFailedJoin);
var lobby = await LobbyAsyncRequests.Instance.QuickJoinLobbyAsync(m_localUser, m_lobbyColorFilter);
if (lobby != null)
{
LobbyConverters.RemoteToLocal(lobby, m_localLobby);
OnJoinedLobby();
}
else
{
OnFailedJoin();
}
}
else if (type == MessageType.RenameRequest)
{

}
}
private void OnLeftLobby()
private async void OnLeftLobby()
LobbyAsyncRequests.Instance.LeaveLobbyAsync(m_localLobby.LobbyID, ResetLocalLobby);
#pragma warning disable 4014
LobbyAsyncRequests.Instance.LeaveLobbyAsync(m_localLobby.LobbyID);
#pragma warning restore 4014
ResetLocalLobby();
m_LobbyContentUpdater.EndTracking();
m_vivoxSetup.LeaveLobbyChannel();

Locator.Get.Messenger.Unsubscribe(this);
if (!string.IsNullOrEmpty(m_localLobby?.LobbyID))
{
LobbyAsyncRequests.Instance.LeaveLobbyAsync(m_localLobby?.LobbyID, null);
#pragma warning disable 4014
LobbyAsyncRequests.Instance.LeaveLobbyAsync(m_localLobby?.LobbyID);
#pragma warning restore 4014
m_localLobby = null;
}
}

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


{
Dictionary<string, LobbyUser> m_LobbyUsers = new Dictionary<string, LobbyUser>();
public Dictionary<string, LobbyUser> LobbyUsers => m_LobbyUsers;
public bool pullUpdate;
public bool canPullUpdate;
#region LocalLobbyData
public struct LobbyData

1
Assets/Scripts/GameLobby/Infrastructure/LogHandlerSettings.cs


private void Awake()
{
LogHandler.Get().mode = m_editorLogVerbosity;
Debug.Log($"Starting project with Log Level : {m_editorLogVerbosity.ToString()}");
Locator.Get.Messenger.Subscribe(this);
}
private void OnDestroy()

24
Assets/Scripts/GameLobby/Lobby/LobbyAPIInterface.cs


using System;
using System.Collections.Generic;
using Unity.Services.Lobbies.Models;
namespace LobbyRelaySample.lobby
{

public static class LobbyAPIInterface
{
private const int k_maxLobbiesToShow = 16; // If more are necessary, consider retrieving paginated results or using filters.
/* TODO Delete LobbyAPIInterface
public static void CreateLobbyAsync(string requesterUASId, string lobbyName, int maxPlayers, bool isPrivate, Dictionary<string, PlayerDataObject> localUserData, Action<Lobby> onComplete)
{
CreateLobbyOptions createOptions = new CreateLobbyOptions

AsyncRequestLobby.Instance.DoRequest(task, onComplete);
}
public static void QueryAllLobbiesAsync(List<QueryFilter> filters, Action<QueryResponse> onComplete)
{
QueryLobbiesOptions queryOptions = new QueryLobbiesOptions
{
Count = k_maxLobbiesToShow,
Filters = filters
};
var task = LobbyService.Instance.QueryLobbiesAsync(queryOptions);
AsyncRequestLobby.Instance.DoRequest(task, onComplete);
}
public static void GetLobbyAsync(string lobbyId, Action<Lobby> onComplete)
{
var task = LobbyService.Instance.GetLobbyAsync(lobbyId);
AsyncRequestLobby.Instance.DoRequest(task, onComplete);
}
/// <summary>
/// Uupdates custom data to the lobby, for all to see.
/// </summary>

};
var task = LobbyService.Instance.UpdatePlayerAsync(lobbyId, playerId, updateOptions);
AsyncRequestLobby.Instance.DoRequest(task, onComplete);
}
}*/
public static void SubscribeToLobbyUpdates(string lobbyId, LobbyEventCallbacks lobbyEvent, Action<ILobbyEvents> onLobbySubscribed)
{

310
Assets/Scripts/GameLobby/Lobby/LobbyAsyncRequests.cs


using LobbyRelaySample.lobby;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Unity.Services.Authentication;
using Unity.Services.Lobbies;
using Unity.Services.Lobbies.Models;

/// An abstraction layer between the direct calls into the Lobby API and the outcomes you actually want. E.g. you can request to get a readable list of
/// current lobbies and not need to make the query call directly.
/// </summary>
public class LobbyAsyncRequests
public class LobbyAsyncRequests : IDisposable
private const int k_maxLobbiesToShow = 16; // If more are necessary, consider retrieving paginated results or using filters.
public static LobbyAsyncRequests Instance
{

//Once connected to a lobby, cache the local lobby object so we don't query for it for every lobby operation.
// (This assumes that the player will be actively in just one lobby at a time, though they could passively be in more.)
Lobby m_RemoteLobby;
/// <summary>
/// Store the LobbySubscription so we can unsubscribe later.
/// </summary>

return data;
}
//TODO Back to Polling i Guess
void BeginListening(string lobbyID)
{
m_lobbyEvents = new LobbyEventCallbacks();

void EndListening()
{
if (m_lobbySubscription == null)
{
Debug.LogError("Can't End listening without first listening to the lobby Callbacks.");
return;
}
m_lobbySubscription.UnsubscribeAsync();
m_RemoteLobby = null;
m_lobbySubscription = null;

/// <summary>
/// Attempt to create a new lobby and then join it.
/// </summary>
public void CreateLobbyAsync(string lobbyName, int maxPlayers, bool isPrivate, LobbyUser localUser, Action<Lobby> onSuccess, Action onFailure)
public async Task<Lobby> CreateLobbyAsync(string lobbyName, int maxPlayers, bool isPrivate, LobbyUser localUser)
if (!m_rateLimitHost.CanCall())
if (m_rateLimitHost.IsInCooldown)
onFailure?.Invoke();
return;
return null;
string uasId = AuthenticationService.Instance.PlayerId;
LobbyAPIInterface.CreateLobbyAsync(uasId, lobbyName, maxPlayers, isPrivate, CreateInitialPlayerData(localUser), OnLobbyCreated);
void OnLobbyCreated(Lobby response)
try
if (response == null)
onFailure?.Invoke();
else
string uasId = AuthenticationService.Instance.PlayerId;
CreateLobbyOptions createOptions = new CreateLobbyOptions
JoinLobby(response);
onSuccess?.Invoke(response); // The Create request automatically joins the lobby, so we need not take further action.
}
IsPrivate = isPrivate,
Player = new Player(id: uasId, data: CreateInitialPlayerData(localUser))
};
var lobby = await LobbyService.Instance.CreateLobbyAsync(lobbyName, maxPlayers, createOptions);
JoinLobby(lobby);
return lobby;
}
catch (Exception ex)
{
Debug.LogError($"Lobby Create failed:\n{ex}");
return null;
public async Task<Lobby> GetLobbyAsync(string lobbyId)
{
await m_rateLimitQuery.WaitUntilCooldown();
return await LobbyService.Instance.GetLobbyAsync(lobbyId);
}
public void JoinLobbyAsync(string lobbyId, string lobbyCode, LobbyUser localUser, Action<Lobby> onSuccess, Action onFailure)
public async Task<Lobby> JoinLobbyAsync(string lobbyId, string lobbyCode, LobbyUser localUser)
if (!m_rateLimitJoin.CanCall() ||
if (m_rateLimitJoin.IsInCooldown ||
onFailure?.Invoke();
UnityEngine.Debug.LogWarning("Join Lobby hit the rate limit.");
return;
return null;
Lobby joinedLobby = null;
var playerData = CreateInitialPlayerData(localUser);
LobbyAPIInterface.JoinLobbyAsync_ById(uasId, lobbyId, CreateInitialPlayerData(localUser), OnLobbyJoined);
{
JoinLobbyByIdOptions joinOptions = new JoinLobbyByIdOptions { Player = new Player(id: uasId, data: playerData) };
joinedLobby = await LobbyService.Instance.JoinLobbyByIdAsync(lobbyId, joinOptions);
}
LobbyAPIInterface.JoinLobbyAsync_ByCode(uasId, lobbyCode, CreateInitialPlayerData(localUser), OnLobbyJoined);
void OnLobbyJoined(Lobby response)
if (response == null)
onFailure?.Invoke();
else
{
JoinLobby(response);
onSuccess?.Invoke(response);
}
JoinLobbyByCodeOptions joinOptions = new JoinLobbyByCodeOptions { Player = new Player(id: uasId, data: playerData) };
joinedLobby = await LobbyService.Instance.JoinLobbyByCodeAsync(lobbyCode, joinOptions);
JoinLobby(joinedLobby);
return joinedLobby;
public void QuickJoinLobbyAsync(LobbyUser localUser, LobbyColor limitToColor = LobbyColor.None, Action<Lobby> onSuccess = null, Action onFailure = null)
public async Task<Lobby> QuickJoinLobbyAsync(LobbyUser localUser, LobbyColor limitToColor = LobbyColor.None)
if (!m_rateLimitQuickJoin.CanCall())
if (m_rateLimitQuickJoin.IsInCooldown)
onFailure?.Invoke();
return;
return null;
LobbyAPIInterface.QuickJoinLobbyAsync(uasId, filters, CreateInitialPlayerData(localUser), OnLobbyJoined);
void OnLobbyJoined(Lobby response)
var joinRequest = new QuickJoinLobbyOptions
if (response == null)
onFailure?.Invoke();
else
{
JoinLobby(response);
onSuccess?.Invoke(response);
}
}
Filter = filters,
Player = new Player(id: uasId, data: CreateInitialPlayerData(localUser))
};
var lobby = await LobbyService.Instance.QuickJoinLobbyAsync(joinRequest);
JoinLobby(lobby);
return lobby;
}
void JoinLobby(Lobby response)

/// Used for getting the list of all active lobbies, without needing full info for each.
/// </summary>
/// <param name="onListRetrieved">If called with null, retrieval was unsuccessful. Else, this will be given a list of contents to display, as pairs of a lobby code and a display string for that lobby.</param>
public void RetrieveLobbyListAsync(Action<QueryResponse> onListRetrieved, Action<QueryResponse> onError = null, LobbyColor limitToColor = LobbyColor.None)
public async Task<QueryResponse> RetrieveLobbyListAsync(LobbyColor limitToColor = LobbyColor.None)
await m_rateLimitQuery.WaitUntilCooldown();
if (!m_rateLimitQuery.CanCall())
{
onListRetrieved?.Invoke(null);
m_rateLimitQuery.EnqueuePendingOperation(() => { RetrieveLobbyListAsync(onListRetrieved, onError, limitToColor); });
UnityEngine.Debug.LogWarning("Retrieve Lobby list hit the rate limit. Will try again soon...");
return;
}
LobbyAPIInterface.QueryAllLobbiesAsync(filters, OnLobbyListRetrieved);
void OnLobbyListRetrieved(QueryResponse response)
QueryLobbiesOptions queryOptions = new QueryLobbiesOptions
if (response != null)
onListRetrieved?.Invoke(response);
else
onError?.Invoke(response);
}
Count = k_maxLobbiesToShow,
Filters = filters
};
return await LobbyService.Instance.QueryLobbiesAsync(queryOptions);
}
private List<QueryFilter> LobbyColorToFilters(LobbyColor limitToColor)

/// Attempt to leave a lobby, and then delete it if no players remain.
/// </summary>
/// <param name="onComplete">Called once the request completes, regardless of success or failure.</param>
public void LeaveLobbyAsync(string lobbyId, Action onComplete)
public async Task LeaveLobbyAsync(string lobbyId)
LobbyAPIInterface.LeaveLobbyAsync(uasId, lobbyId, OnLeftLobby);
void OnLeftLobby()
{
onComplete?.Invoke();
m_RemoteLobby = null;
EndListening();
// Lobbies will automatically delete the lobby if unoccupied, so we don't need to take further action.
}
await LobbyService.Instance.RemovePlayerAsync(lobbyId, uasId);
m_RemoteLobby = null;
EndListening();
// Lobbies will automatically delete the lobby if unoccupied, so we don't need to take further action.
public void UpdatePlayerDataAsync(Dictionary<string, string> data, Action onComplete)
public async Task UpdatePlayerDataAsync(Dictionary<string, string> data)
if (!ShouldUpdateData(() => { UpdatePlayerDataAsync(data, onComplete); }, onComplete, false))
return;
await m_rateLimitQuery.WaitUntilCooldown();
string playerId = Locator.Get.Identity.GetSubIdentity(Auth.IIdentityType.Auth).GetContent("id");
Dictionary<string, PlayerDataObject> dataCurr = new Dictionary<string, PlayerDataObject>();
foreach (var dataNew in data)

dataCurr.Add(dataNew.Key, dataObj);
}
LobbyAPIInterface.UpdatePlayerAsync(m_RemoteLobby.Id, playerId, dataCurr, (result) =>
UpdatePlayerOptions updateOptions = new UpdatePlayerOptions
onComplete?.Invoke();
}, null, null);
Data = dataCurr,
AllocationId = null,
ConnectionInfo = null
};
await LobbyService.Instance.UpdatePlayerAsync(m_RemoteLobby.Id, playerId, updateOptions);
public void UpdatePlayerRelayInfoAsync(string allocationId, string connectionInfo, Action onComplete)
public async Task UpdatePlayerRelayInfoAsync(string allocationId, string connectionInfo)
if (!ShouldUpdateData(() => { UpdatePlayerRelayInfoAsync(allocationId, connectionInfo, onComplete); }, onComplete, true)) // Do retry here since the RelayUtpSetup that called this might be destroyed right after this.
return;
await m_rateLimitQuery.WaitUntilCooldown();
await AwaitRemoteLobby();
LobbyAPIInterface.UpdatePlayerAsync(m_RemoteLobby.Id, playerId, new Dictionary<string, PlayerDataObject>(), (r) => { onComplete?.Invoke(); }, allocationId, connectionInfo);
UpdatePlayerOptions updateOptions = new UpdatePlayerOptions
{
Data = new Dictionary<string, PlayerDataObject>(),
AllocationId = allocationId,
ConnectionInfo = connectionInfo
};
await LobbyService.Instance.UpdatePlayerAsync(m_RemoteLobby.Id, playerId, updateOptions);
public void UpdateLobbyDataAsync(Dictionary<string, string> data, Action onComplete)
public async Task UpdateLobbyDataAsync(Dictionary<string, string> data)
if (!ShouldUpdateData(() => { UpdateLobbyDataAsync(data, onComplete); }, onComplete, false))
return;
await m_rateLimitQuery.WaitUntilCooldown();
Dictionary<string, DataObject> dataCurr = m_RemoteLobby.Data ?? new Dictionary<string, DataObject>();

shouldLock = lobbyState != LobbyState.Lobby;
}
}
LobbyAPIInterface.UpdateLobbyAsync(m_RemoteLobby.Id, dataCurr, shouldLock, (result) =>
{
if (result != null)
m_RemoteLobby = result;
onComplete?.Invoke();
});
UpdateLobbyOptions updateOptions = new UpdateLobbyOptions { Data = dataCurr, IsLocked = shouldLock };
var result = await LobbyService.Instance.UpdateLobbyAsync(m_RemoteLobby.Id, updateOptions);
if (result != null)
m_RemoteLobby = result;
/// <summary>
/// If we are in the middle of another operation, hold onto any pending ones until after that.
/// If we aren't in a lobby yet, leave it to the caller to decide what to do, since some callers might need to retry and others might not.
/// </summary>
private bool ShouldUpdateData(Action caller, Action onComplete, bool shouldRetryIfLobbyNull)
{
if (m_rateLimitQuery.IsInCooldown)
{
m_rateLimitQuery.EnqueuePendingOperation(caller);
return false;
}
if (m_RemoteLobby == null)
{
if (shouldRetryIfLobbyNull)
m_rateLimitQuery.EnqueuePendingOperation(caller);
onComplete?.Invoke();
return false;
}
return true;
}
private float m_heartbeatTime = 0;
private const float k_heartbeatPeriod = 8; // The heartbeat must be rate-limited to 5 calls per 30 seconds. We'll aim for longer in case periods don't align.

}
}
public class RateLimitCooldown : Observed<RateLimitCooldown>
async Task AwaitRemoteLobby()
private float m_timeSinceLastCall = float.MaxValue;
private readonly float m_cooldownTime;
private Queue<Action> m_pendingOperations = new Queue<Action>();
while (m_RemoteLobby == null)
await Task.Delay(100);
}
public void EnqueuePendingOperation(Action action)
{
//We probably dont want many of the same actions added to fire off multiple times.
if (!m_pendingOperations.Contains(action))
return;
public void Dispose()
{
m_pendingOperations.Enqueue(action);
}
}
public class RateLimitCooldown
{
public Action<bool> onCooldownChange;
public readonly float m_CooldownSeconds;
public readonly int m_CoolDownMS;
Queue<Task> m_TaskQueue = new Queue<Task>();
Task m_DequeuedTask;
private bool m_isInCooldown = false;
private bool m_IsInCooldown = false;
get => m_isInCooldown;
get => m_IsInCooldown;
if (m_isInCooldown != value)
if (m_IsInCooldown != value)
m_isInCooldown = value;
OnChanged(this);
m_IsInCooldown = value;
onCooldownChange?.Invoke(m_IsInCooldown);
public RateLimitCooldown(float cooldownTime)
public RateLimitCooldown(float cooldownSeconds)
m_cooldownTime = cooldownTime;
m_CooldownSeconds = cooldownSeconds;
m_CoolDownMS = Mathf.FloorToInt(m_CooldownSeconds * 1000);
public bool CanCall()
public async Task WaitUntilCooldown() //TODO YAGNI Handle Multiple commands? Return bool if already waiting?
if (m_timeSinceLastCall < m_cooldownTime)
return false;
else
//No Queue!
if (CanCall())
return;
while (m_IsInCooldown)
Locator.Get.UpdateSlow.Subscribe(OnUpdate, m_cooldownTime);
m_timeSinceLastCall = 0;
IsInCooldown = true;
return true;
await Task.Delay(100);
private void OnUpdate(float dt)
bool CanCall()
m_timeSinceLastCall += dt;
if (m_timeSinceLastCall >= m_cooldownTime)
if (!IsInCooldown)
IsInCooldown = false;
if (!m_isInCooldown) // It's possible that by setting IsInCooldown, something called CanCall immediately, in which case we want to stay on UpdateSlow.
{
Locator.Get.UpdateSlow.Unsubscribe(OnUpdate); // Note that this is after IsInCooldown is set, to prevent an Observer from kicking off CanCall again immediately.
int numPending = m_pendingOperations.Count; // It's possible a pending operation will re-enqueue itself or new operations, which should wait until the next loop.
for (; numPending > 0; numPending--)
m_pendingOperations.Dequeue()?.Invoke(); // Note: If this ends up enqueuing many operations, we might need to batch them and/or ensure they don't all execute at once.
}
#pragma warning disable 4014
CoolDownAsync();
#pragma warning restore 4014
return true;
else return false;
public override void CopyObserved(RateLimitCooldown oldObserved)
async Task CoolDownAsync()
/* This behavior isn't needed; we're just here for the OnChanged event management. */
if (m_IsInCooldown)
return;
IsInCooldown = true;
await Task.Delay(m_CoolDownMS);
if (m_TaskQueue.Count > 0)
{
m_DequeuedTask = m_TaskQueue.Dequeue();
await CoolDownAsync();
}
IsInCooldown = false;
}
}

15
Assets/Scripts/GameLobby/Lobby/LobbyContentUpdater.cs


using System;
using LobbyRelaySample.lobby;
using Unity.Services.Lobbies.Models;
using UnityEngine;
namespace LobbyRelaySample
{

return;
}
if (changed.pullUpdate)
if (changed.canPullUpdate)
changed.pullUpdate = false;
changed.canPullUpdate = false;
return;
}

void DoLobbyDataPush()
{
LobbyAsyncRequests.Instance.UpdateLobbyDataAsync(LobbyConverters.LocalToRemoteData(m_LocalLobby), null);
#pragma warning disable 4014
LobbyAsyncRequests.Instance.UpdateLobbyDataAsync(LobbyConverters.LocalToRemoteData(m_LocalLobby));
#pragma warning restore 4014
LobbyAsyncRequests.Instance.UpdatePlayerDataAsync(LobbyConverters.LocalToRemoteUserData(m_LocalUser), null);
#pragma warning disable 4014
LobbyAsyncRequests.Instance.UpdatePlayerDataAsync(LobbyConverters.LocalToRemoteUserData(m_LocalUser));
#pragma warning restore 4014
m_LocalLobby.pullUpdate = true;
m_LocalLobby.canPullUpdate = true;
//synching our local lobby
LobbyConverters.RemoteToLocal(lobby, m_LocalLobby);

5
Assets/Scripts/GameLobby/NGO/InGameRunner.cs


private void FinishInitialize()
{
m_symbolContainerInstance = NetworkObject.Instantiate(m_symbolContainerPrefab).transform;
m_symbolContainerInstance.GetComponent<NetworkObject>().Spawn();
ResetPendingSymbolPositions();
m_killVolume.Initialize(OnSymbolDeactivated);
}

playerCursor.name += clientData.name;
m_dataStore.AddPlayer(clientData.id, clientData.name);
bool areAllPlayersConnected = NetworkManager.ConnectedClients.Count >= m_expectedPlayerCount; // The game will begin at this point, or else there's a timeout for booting any unconnected players.
bool areAllPlayersConnected = NetworkManager.Singleton.ConnectedClients.Count >= m_expectedPlayerCount; // The game will begin at this point, or else there's a timeout for booting any unconnected players.
VerifyConnectionConfirm_ClientRpc(clientData.id, areAllPlayersConnected);
}

{
int index = SequenceSelector.k_symbolCount - m_pendingSymbolPositions.Count;
Vector3 pendingPos = m_pendingSymbolPositions.Dequeue();
var symbolObj = Instantiate(m_symbolObjectPrefab);
var symbolObj = Instantiate(m_symbolObjectPrefab, m_symbolContainerInstance);
symbolObj.NetworkObject.Spawn();
symbolObj.name = "Symbol" + index;
symbolObj.NetworkObject.TrySetParent(m_symbolContainerInstance, false);

2
Assets/Scripts/GameLobby/NGO/PlayerCursor.cs


[SerializeField] private ParticleSystem m_onClickParticles = default;
[SerializeField] private TMPro.TMP_Text m_nameOutput = default;
private Camera m_mainCamera;
private NetworkVariable<Vector3> m_position = new NetworkVariable<Vector3>(NetworkVariableReadPermission.Everyone, Vector3.zero); // (Using a NetworkTransform to sync position would also work.)
private NetworkVariable<Vector3> m_position = new NetworkVariable<Vector3>( Vector3.zero); // (Using a NetworkTransform to sync position would also work.)
private ulong m_localId;
// If the local player cursor spawns before this cursor's owner, the owner's data won't be available yet. This is used to retrieve the data later.

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


using System;
using System.Threading.Tasks;
using Unity.Netcode.Transports.UTP;
using UnityEngine;
namespace LobbyRelaySample.ngo

/// </summary>
public class SetupInGame : MonoBehaviour, IReceiveMessages
{
[SerializeField] private GameObject m_prefabNetworkManager = default;
[SerializeField] private GameObject m_IngameRunnerPrefab = default;
private GameObject m_inGameManagerObj;
private NetworkManager m_networkManager;
private InGameRunner m_inGameRunner;
private bool m_doesNeedCleanup = false;

/// 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>
private void CreateNetworkManager()
private async Task CreateNetworkManager()
m_inGameManagerObj = GameObject.Instantiate(m_prefabNetworkManager);
m_networkManager = m_inGameManagerObj.GetComponentInChildren<NetworkManager>();
m_inGameRunner = m_inGameManagerObj.GetComponentInChildren<InGameRunner>();
m_inGameRunner.Initialize(OnConnectionVerified, m_lobby.PlayerCount, OnGameEnd, m_localUser);
UnityTransport transport = m_inGameManagerObj.GetComponentInChildren<UnityTransport>();
UnityTransport transport = NetworkManager.Singleton.GetComponentInChildren<UnityTransport>();
m_inGameManagerObj.AddComponent<RelayUtpNGOSetupHost>().Initialize(this, m_lobby, () => { m_initializeTransport(transport); m_networkManager.StartHost(); });
NetworkManager.Singleton.gameObject.AddComponent<RelayUtpNGOSetupHost>().Initialize(this, m_lobby, () => { m_initializeTransport(transport); NetworkManager.Singleton.StartHost(); });
m_inGameManagerObj.AddComponent<RelayUtpNGOSetupClient>().Initialize(this, m_lobby, () => { m_initializeTransport(transport); m_networkManager.StartClient(); });
NetworkManager.Singleton.gameObject.AddComponent<RelayUtpNGOSetupClient>().Initialize(this, m_lobby, () => { m_initializeTransport(transport); NetworkManager.Singleton.StartClient(); });
await Task.Delay(1);
m_inGameRunner = Instantiate(m_IngameRunnerPrefab).GetComponentInChildren<InGameRunner>();
m_inGameRunner.Initialize(OnConnectionVerified, m_lobby.PlayerCount, OnGameEnd, m_localUser);
}
private void OnConnectionVerified()

{
if (m_doesNeedCleanup)
{
GameObject.Destroy(m_inGameManagerObj); // Since this destroys the NetworkManager, that will kick off cleaning up networked objects.
NetworkManager.Singleton.Shutdown();
GameObject.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;

14
Assets/Scripts/GameLobby/NGO/SymbolContainer.cs


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

transform.position = Vector3.up * 10;
}
else
{
this.enabled = false; // Just disabling this script, not the whole GameObject.
}
}

4
Assets/Scripts/GameLobby/Relay/RelayAPIInterface.cs


else
onComplete?.Invoke(response);
}
;
}
/// <summary>

else
onComplete?.Invoke(response);
}
;
}
}
}

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


using System.Collections.Generic;
using System.Threading.Tasks;
using Unity.Networking.Transport;
namespace LobbyRelaySample.relay

UnityEngine.Debug.LogWarning("Disconnecting a client due to a disconnect message.");
conn.Disconnect(m_networkDriver);
m_connections.Remove(conn);
LobbyAsyncRequests.Instance.GetRateLimit(LobbyAsyncRequests.RequestType.Query).EnqueuePendingOperation(WaitToCheckForUsers);
return;
#pragma warning disable 4014
var queryCooldownMilliseconds = LobbyAsyncRequests.Instance.GetRateLimit(LobbyAsyncRequests.RequestType.Query)
.m_CoolDownMS;
void WaitToCheckForUsers()
{ LobbyAsyncRequests.Instance.GetRateLimit(LobbyAsyncRequests.RequestType.Query).EnqueuePendingOperation(CheckIfAllUsersReady);
}
WaitAndCheckUsers(queryCooldownMilliseconds*2);
#pragma warning restore 4014
return;
}
async Task WaitAndCheckUsers(int milliSeconds)
{
await Task.Delay(milliSeconds);
CheckIfAllUsersReady();
}
protected override void ProcessDisconnectEvent(NetworkConnection conn, DataStreamReader strm)

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


using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using Unity.Networking.Transport;
using Unity.Networking.Transport.Relay;
using Unity.Services.Relay.Models;

m_localLobby.RelayCode = relayCode;
m_localLobby.RelayServer = new ServerAddress(AddressFromEndpoint(m_endpointForServer), m_endpointForServer.Port);
m_joinState |= JoinState.Joined;
#pragma warning disable 4014
#pragma warning restore 4014
}
protected override void OnBindingComplete()

{
Debug.Log("Relay host is bound.");
m_joinState |= JoinState.Bound;
#pragma warning disable 4014
#pragma warning restore 4014
private void CheckForComplete()
private async Task CheckForComplete()
{
if (m_joinState == (JoinState.Joined | JoinState.Bound) && this != null) // this will equal null (i.e. this component has been destroyed) if the host left the lobby during the Relay connection sequence.
{

m_onJoinComplete(true, host);
LobbyAsyncRequests.Instance.UpdatePlayerRelayInfoAsync(m_allocation.AllocationId.ToString(), m_localLobby.RelayCode, null);
await LobbyAsyncRequests.Instance.UpdatePlayerRelayInfoAsync(m_allocation.AllocationId.ToString(), m_localLobby.RelayCode);
}
}
}

protected override void OnBindingComplete()
{
StartCoroutine(ConnectToServer());
#pragma warning disable 4014
ConnectToServer();
#pragma warning restore 4014
private IEnumerator ConnectToServer()
private async Task ConnectToServer()
{
// Once the client is bound to the Relay server, send a connection request.
m_connections.Add(m_networkDriver.Connect(m_endpointForServer));

yield return null;
await Task.Delay(100);
}
if (m_networkDriver.GetConnectionState(m_connections[0]) != NetworkConnection.State.Connected)
{

RelayUtpClient client = gameObject.AddComponent<RelayUtpClient>();
client.Initialize(m_networkDriver, m_connections, m_localUser, m_localLobby);
m_onJoinComplete(true, client);
LobbyAsyncRequests.Instance.UpdatePlayerRelayInfoAsync(m_allocation.AllocationId.ToString(), m_localLobby.RelayCode, null);
await LobbyAsyncRequests.Instance.UpdatePlayerRelayInfoAsync(m_allocation.AllocationId.ToString(), m_localLobby.RelayCode);
}
}
}

127
Assets/Scripts/GameLobby/Tests/PlayMode/LobbyRoundtripTests.cs


using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Unity.Services.Lobbies;
using Test.Tools;
using LobbyRelaySample;
using LobbyAPIInterface = LobbyRelaySample.lobby.LobbyAPIInterface;
namespace Test
{

private LobbyRelaySample.Auth.SubIdentity_Authentication m_auth;
private bool m_didSigninComplete = false;
private Dictionary<string, PlayerDataObject> m_mockUserData; // This is handled in the LobbyAsyncRequest calls normally, but we need to supply this for the direct Lobby API calls.
LobbyUser m_LocalUser;
[OneTimeSetUp]
public void Setup()
{

m_LocalUser = new LobbyUser(true);
}
[UnityTearDown]

{ LobbyAPIInterface.DeleteLobbyAsync(m_workingLobbyId, null);
{ yield return AsyncTestHelper.Await(async ()=> await LobbyAsyncRequests.Instance.LeaveLobbyAsync(m_workingLobbyId));
m_workingLobbyId = null;
}
yield return new WaitForSeconds(0.5f); // We need a yield anyway, so wait long enough to probably delete the lobby. There currently (6/22/2021) aren't other tests that would have issues if this took longer.

public IEnumerator DoRoundtrip()
{
#region Setup
// Wait a reasonable amount of time for sign-in to complete.
if (!m_didSigninComplete)
yield return new WaitForSeconds(3);

// Since we're signed in through the same pathway as the actual game, the list of lobbies will include any that have been made in the game itself, so we should account for those.
// If you want to get around this, consider having a secondary project using the same assets with its own credentials.
yield return new WaitForSeconds(1); // To prevent a possible 429 with the upcoming Query request, in case a previous test had one; Query requests can only occur at a rate of 1 per second.
yield return
new WaitForSeconds(
1); // To prevent a possible 429 with the upcoming Query request, in case a previous test had one; Query requests can only occur at a rate of 1 per second.
Debug.Log("Getting Lobby List 1");
float timeout = 5;
LobbyAPIInterface.QueryAllLobbiesAsync(new List<QueryFilter>(), (qr) => { queryResponse = qr; });
while (queryResponse == null && timeout > 0)
{ yield return new WaitForSeconds(0.25f);
timeout -= 0.25f;
}
Assert.Greater(timeout, 0, "Timeout check (query #0)");
yield return AsyncTestHelper.Await(async () => queryResponse = await LobbyAsyncRequests.Instance.RetrieveLobbyListAsync());
Debug.Log("Got Lobby List 1");
timeout = 5;
LobbyAPIInterface.CreateLobbyAsync(m_auth.GetContent("id"), lobbyName, 100, false, m_mockUserData, (r) => { createResponse = r; });
while (createResponse == null && timeout > 0)
{ yield return new WaitForSeconds(0.25f);
timeout -= 0.25f;
}
Assert.Greater(timeout, 0, "Timeout check (create)");
yield return AsyncTestHelper.Await(async () =>
createResponse = await LobbyAsyncRequests.Instance.CreateLobbyAsync(
lobbyName,
100,
false,
m_LocalUser));
Assert.IsNotNull(createResponse, "CreateLobbyAsync should return a non-null result.");
m_workingLobbyId = createResponse.Id;
Assert.AreEqual(lobbyName, createResponse.Name, "Created lobby should match the provided name.");

queryResponse = null;
timeout = 5;
LobbyAPIInterface.QueryAllLobbiesAsync(new List<QueryFilter>(), (qr) => { queryResponse = qr; });
while (queryResponse == null && timeout > 0)
{ yield return new WaitForSeconds(0.25f);
timeout -= 0.25f;
}
Assert.Greater(timeout, 0, "Timeout check (query #1)");
Debug.Log("Getting Lobby List 2");
yield return AsyncTestHelper.Await(async () => queryResponse = await LobbyAsyncRequests.Instance.RetrieveLobbyListAsync());
Debug.Log("Got Lobby List 2");
Assert.IsNotNull(queryResponse, "QueryAllLobbiesAsync should return a non-null result. (#1)");
Assert.AreEqual(1 + numLobbiesIni, queryResponse.Results.Count, "Queried lobbies list should contain the test lobby.");
Assert.IsTrue(queryResponse.Results.Where(r => r.Name == lobbyName).Count() == 1, "Checking queried lobby for name.");

Lobby getResponse = null;
timeout = 5;
LobbyAPIInterface.GetLobbyAsync(createResponse.Id, (r) => { getResponse = r; });
while (getResponse == null && timeout > 0)
{ yield return new WaitForSeconds(0.25f);
timeout -= 0.25f;
}
Assert.Greater(timeout, 0, "Timeout check (get)");
Assert.IsNotNull(getResponse, "GetLobbyAsync should return a non-null result.");
Assert.AreEqual(lobbyName, getResponse.Name, "Checking the lobby we got for name.");
Assert.AreEqual(m_workingLobbyId, getResponse.Id, "Checking the lobby we got for ID.");
Debug.Log("Getting Lobby");
Lobby lobby = null;
yield return AsyncTestHelper.Await(async ()=> lobby = await LobbyAsyncRequests.Instance.GetLobbyAsync(createResponse.Id));
Debug.Log("Got Lobby");
Assert.IsNotNull(lobby, "GetLobbyAsync should return a non-null result.");
Assert.AreEqual(lobbyName, lobby.Name, "Checking the lobby we got for name.");
Assert.AreEqual(m_workingLobbyId, lobby.Id, "Checking the lobby we got for ID.");
bool didDeleteFinish = false;
timeout = 5;
LobbyAPIInterface.DeleteLobbyAsync(m_workingLobbyId, () => { didDeleteFinish = true; });
while (timeout > 0 && !didDeleteFinish)
{ yield return new WaitForSeconds(0.25f);
timeout -= 0.25f;
}
Assert.Greater(timeout, 0, "Timeout check (delete)");
yield return AsyncTestHelper.Await(async ()=> await LobbyAsyncRequests.Instance.LeaveLobbyAsync(m_workingLobbyId));
QueryResponse queryResponseTwo = null;
timeout = 5;
LobbyAPIInterface.QueryAllLobbiesAsync(new List<QueryFilter>(), (qr) => { queryResponseTwo = qr; });
while (queryResponseTwo == null && timeout > 0)
{ yield return new WaitForSeconds(0.25f);
timeout -= 0.25f;
}
Assert.Greater(timeout, 0, "Timeout check (query #2)");
Debug.Log("Getting Lobby List 3");
yield return AsyncTestHelper.Await(async () => queryResponse = await LobbyAsyncRequests.Instance.RetrieveLobbyListAsync());
Debug.Log("Got Lobby List 3");
Assert.AreEqual(numLobbiesIni, queryResponseTwo.Results.Count, "Queried lobbies list should be empty.");
Assert.AreEqual(numLobbiesIni, queryResponse.Results.Count, "Queried lobbies list should be empty.");
// Some error messages might be asynchronous, so to reduce spillover into other tests, just wait here for a bit before proceeding.
yield return new WaitForSeconds(3);

/// If the Lobby create call fails, we want to ensure we call onComplete so we can act on the failure.
/// If the Lobby create call fails, we return null
public IEnumerator OnCompletesOnFailure()
public IEnumerator CreateFailsWithNull()
{
if (!m_didSigninComplete)
yield return new WaitForSeconds(3);

bool? didComplete = null;
LobbyAPIInterface.CreateLobbyAsync("ThisStringIsInvalidHere", "lobby name", 123, false, m_mockUserData, (r) => { didComplete = (r == null); });
float timeout = 5;
while (didComplete == null && timeout > 0)
{ yield return new WaitForSeconds(0.25f);
timeout -= 0.25f;
}
Lobby createLobby = null;
yield return AsyncTestHelper.Await(async () =>
createLobby = await LobbyAsyncRequests.Instance.CreateLobbyAsync(
"lobby name",
123,
false,
m_LocalUser));
Assert.Greater(timeout, 0, "Timeout check");
Assert.NotNull(didComplete, "Should have called onComplete, even if the async request failed.");
Assert.True(didComplete, "The returned object will be null, so expect to need to handle it.");
Assert.Null(createLobby, "The returned object will be null, so expect to need to handle it.");
}
}
}

8
Assets/Scripts/GameLobby/UI/RateLimitVisibility.cs


private void Start()
{
LobbyAsyncRequests.Instance.GetRateLimit(m_requestType).onChanged += UpdateVisibility;
LobbyAsyncRequests.Instance.GetRateLimit(m_requestType).onCooldownChange += UpdateVisibility;
LobbyAsyncRequests.Instance.GetRateLimit(m_requestType).onChanged -= UpdateVisibility;
LobbyAsyncRequests.Instance.GetRateLimit(m_requestType).onCooldownChange -= UpdateVisibility;
private void UpdateVisibility(LobbyAsyncRequests.RateLimitCooldown rateLimit)
private void UpdateVisibility(bool isCoolingDown)
if (rateLimit.IsInCooldown)
if (isCoolingDown)
m_target.Hide(m_alphaWhenHidden);
else
m_target.Show();

14
Packages/manifest.json


{
"dependencies": {
"com.unity.2d.sprite": "1.0.0",
"com.unity.collab-proxy": "1.15.13",
"com.unity.collab-proxy": "1.15.15",
"com.unity.ide.rider": "3.0.7",
"com.unity.ide.rider": "3.0.13",
"com.unity.netcode.adapter.utp": "1.0.0-pre.3",
"com.unity.netcode.gameobjects": "1.0.0-pre.2",
"com.unity.netcode.gameobjects": "1.0.0-pre.9",
"com.unity.render-pipelines.universal": "10.8.1",
"com.unity.services.authentication": "1.0.0-pre.37",
"com.unity.render-pipelines.universal": "12.1.6",
"com.unity.services.authentication": "2.0.0",
"com.unity.services.wire": "1.0.0-preview.20",
"com.unity.services.wire": "1.0.0",
"com.unity.toolchain.macos-x86_64-linux-x86_64": "2.0.1",
"com.unity.toolchain.win-x86_64-linux-x86_64": "0.1.20-preview",
"com.unity.transport": "1.0.0-pre.9",
"com.unity.ugui": "1.0.0",

114
Packages/packages-lock.json


"dependencies": {}
},
"com.unity.burst": {
"version": "1.5.5",
"version": "1.6.5",
"depth": 1,
"source": "registry",
"dependencies": {

},
"com.unity.collab-proxy": {
"version": "1.15.13",
"version": "1.15.15",
"depth": 0,
"source": "registry",
"dependencies": {

},
"com.unity.collections": {
"version": "1.1.0",
"depth": 1,
"version": "1.2.3",
"depth": 2,
"com.unity.burst": "1.5.4",
"com.unity.test-framework": "1.1.29"
"com.unity.burst": "1.6.4",
"com.unity.test-framework": "1.1.31"
},
"url": "https://packages.unity.com"
},

"url": "https://packages.unity.com"
},
"com.unity.ide.rider": {
"version": "3.0.7",
"version": "3.0.13",
"depth": 0,
"source": "registry",
"dependencies": {

"url": "https://packages.unity.com"
},
"com.unity.mathematics": {
"version": "1.2.1",
"version": "1.2.5",
"com.unity.netcode.adapter.utp": {
"version": "1.0.0-pre.3",
"com.unity.netcode.gameobjects": {
"version": "1.0.0-pre.9",
"com.unity.netcode.gameobjects": "1.0.0-pre.3",
"com.unity.transport": "1.0.0-pre.7"
},
"url": "https://packages.unity.com"
},
"com.unity.netcode.gameobjects": {
"version": "1.0.0-pre.3",
"depth": 1,
"source": "registry",
"dependencies": {
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.animation": "1.0.0",
"com.unity.collections": "1.0.0-pre.5"
"com.unity.transport": "1.0.0"
},
"url": "https://packages.unity.com"
},

"url": "https://packages.unity.com"
},
"com.unity.nuget.newtonsoft-json": {
"version": "3.0.1",
"version": "3.0.2",
"depth": 1,
"source": "registry",
"dependencies": {},

"version": "10.8.1",
"version": "12.1.6",
"source": "registry",
"source": "builtin",
},
"url": "https://packages.unity.com"
}
"version": "10.8.1",
"version": "12.1.6",
"source": "registry",
"source": "builtin",
"com.unity.mathematics": "1.1.0",
"com.unity.render-pipelines.core": "10.8.1",
"com.unity.shadergraph": "10.8.1"
},
"url": "https://packages.unity.com"
"com.unity.mathematics": "1.2.1",
"com.unity.burst": "1.5.0",
"com.unity.render-pipelines.core": "12.1.6",
"com.unity.shadergraph": "12.1.6"
}
"version": "4.3.2",
"version": "4.9.1",
"depth": 2,
"source": "registry",
"dependencies": {},

"version": "1.0.0-pre.73",
"depth": 1,
"version": "2.0.0",
"depth": 0,
"com.unity.nuget.newtonsoft-json": "2.0.0",
"com.unity.services.core": "1.1.0-pre.77",
"com.unity.nuget.newtonsoft-json": "3.0.2",
"com.unity.services.core": "1.3.1",
"version": "1.2.0",
"depth": 0,
"version": "1.3.1",
"depth": 1,
"com.unity.nuget.newtonsoft-json": "3.0.1",
"com.unity.nuget.newtonsoft-json": "3.0.2",
"com.unity.modules.androidjni": "1.0.0"
},
"url": "https://packages.unity.com"

"url": "https://packages.unity.com"
},
"com.unity.services.wire": {
"version": "1.0.0-preview.20",
"version": "1.0.0",
"depth": 0,
"source": "registry",
"dependencies": {

"url": "https://packages.unity.com"
},
"com.unity.shadergraph": {
"version": "10.8.1",
"version": "12.1.6",
"source": "registry",
"source": "builtin",
"com.unity.render-pipelines.core": "10.8.1",
"com.unity.searcher": "4.3.2"
},
"url": "https://packages.unity.com"
"com.unity.render-pipelines.core": "12.1.6",
"com.unity.searcher": "4.9.1"
}
"version": "0.1.19-preview",
"version": "2.0.2",
"depth": 1,
"source": "registry",
"dependencies": {},

"version": "0.1.15-preview",
"depth": 0,
"version": "2.0.1",
"depth": 1,
"com.unity.sysroot": "0.1.19-preview"
"com.unity.sysroot": "2.0.2"
},
"url": "https://packages.unity.com"
},

},
"url": "https://packages.unity.com"
},
"com.unity.toolchain.macos-x86_64-linux-x86_64": {
"version": "2.0.1",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.sysroot": "2.0.2",
"com.unity.sysroot.linux-x86_64": "2.0.1"
},
"url": "https://packages.unity.com"
},
"com.unity.toolchain.win-x86_64-linux-x86_64": {
"version": "0.1.20-preview",
"depth": 0,

"url": "https://packages.unity.com"
},
"com.unity.transport": {
"version": "1.0.0-pre.9",
"depth": 0,
"version": "1.0.0",
"depth": 1,
"com.unity.collections": "1.1.0",
"com.unity.burst": "1.5.5",
"com.unity.mathematics": "1.2.1"
"com.unity.collections": "1.2.3",
"com.unity.burst": "1.6.4",
"com.unity.mathematics": "1.2.5"
},
"url": "https://packages.unity.com"
},

9
ProjectSettings/GraphicsSettings.asset


--- !u!30 &1
GraphicsSettings:
m_ObjectHideFlags: 0
serializedVersion: 13
serializedVersion: 14
m_Deferred:
m_Mode: 1
m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0}

- {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0}
m_PreloadedShaders: []
m_PreloadShadersBatchTimeLimit: -1
m_CustomRenderPipeline: {fileID: 0}
m_CustomRenderPipeline: {fileID: 11400000, guid: f54ab92f70892f44eba32f1c414f5b4a, type: 2}
m_TransparencySortMode: 0
m_TransparencySortAxis: {x: 0, y: 0, z: 1}
m_DefaultRenderingPath: 1

m_FogKeepExp2: 1
m_AlbedoSwatchInfos: []
m_LightsUseLinearIntensity: 0
m_LightsUseColorTemperature: 0
m_LightsUseColorTemperature: 1
m_SRPDefaultSettings:
UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: c96e53b1d712ac24eaccfd7f849c709d, type: 2}

27
ProjectSettings/PackageManagerSettings.asset


m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0}
m_Name:
m_EditorClassIdentifier:
m_EnablePreviewPackages: 1
m_EnablePreReleasePackages: 1
m_SeeAllPackageVersions: 0
oneTimeWarningShown: 1
m_Registries:
- m_Id: main

- com.unity.services.authentication
m_IsDefault: 0
m_Capabilities: 0
m_UserSelectedRegistryName:
m_UserSelectedRegistryName: Internal Candidates Registry
m_Modified: 0
m_Original:
m_Id: scoped:Internal Candidates Registry
m_Name: Internal Candidates Registry
m_Url: https://artifactory.prd.it.unity3d.com/artifactory/api/npm/upm-candidates
m_Scopes:
- com.unity.services.wire
- com.unity.services.lobby
- com.unity.services.authentication
m_IsDefault: 0
m_Capabilities: 0
m_Modified: 0
m_Name: Internal Candidates Registry
m_Url: https://artifactory.prd.it.unity3d.com/artifactory/api/npm/upm-candidates
m_Scopes:
- com.unity.services.wire
- com.unity.services.lobby
- com.unity.services.authentication
m_SelectedScopeIndex: 0
m_UserModificationsInstanceId: -824
m_OriginalInstanceId: -828
m_LoadAssets: 0

4
ProjectSettings/ProjectVersion.txt


m_EditorVersion: 2020.3.31f1
m_EditorVersionWithRevision: 2020.3.31f1 (6b54b7616050)
m_EditorVersion: 2021.2.19f1
m_EditorVersionWithRevision: 2021.2.19f1 (602ecdbb2fb0)

3
ProjectSettings/QualitySettings.asset


shadowResolution: 2
shadowProjection: 1
shadowCascades: 4
shadowDistance: 150
shadowDistance: 160
shadowNearPlaneOffset: 3
shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}

Lumin: 5
Nintendo Switch: 5
PS4: 5
Server: 0
Stadia: 5
Standalone: 5
WebGL: 3

2
ProjectSettings/URPProjectSettings.asset


m_Script: {fileID: 11500000, guid: 247994e1f5a72c2419c26a37e9334c01, type: 3}
m_Name:
m_EditorClassIdentifier:
m_LastMaterialVersion: 4
m_LastMaterialVersion: 5

112
Assets/Prefabs/NGO/NetworkManager.prefab


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &5481270937743757918
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5665493986528408842}
- component: {fileID: 5021303663353436182}
- component: {fileID: 1765689956051871792}
m_Layer: 0
m_Name: NetworkManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5665493986528408842
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5481270937743757918}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 52.01943, z: -6}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &5021303663353436182
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5481270937743757918}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 593a2fe42fa9d37498c96f9a383b6521, type: 3}
m_Name:
m_EditorClassIdentifier:
RunInBackground: 0
LogLevel: 1
NetworkConfig:
ProtocolVersion: 0
NetworkTransport: {fileID: 1765689956051871792}
PlayerPrefab: {fileID: 0}
NetworkPrefabs:
- Override: 0
Prefab: {fileID: 3227847727972158006, guid: 905594b4ee5bb864a84af916cc445d1b, type: 3}
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}
- Override: 0
Prefab: {fileID: 5240148789413552765, guid: f42ed38d10b57ec48870f76a7a63389e, type: 3}
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}
- Override: 0
Prefab: {fileID: 8828823320646980938, guid: e371ca3112f9e244ab574b472387b64b, type: 3}
SourcePrefabToOverride: {fileID: 0}
SourceHashToOverride: 0
OverridingTargetPrefab: {fileID: 0}
TickRate: 30
ClientConnectionBufferTimeout: 10
ConnectionApproval: 0
ConnectionData:
EnableTimeResync: 0
TimeResyncInterval: 30
EnsureNetworkVariableLengthSafety: 0
EnableSceneManagement: 1
ForceSamePrefabs: 1
RecycleNetworkIds: 1
NetworkIdRecycleDelay: 120
RpcHashSize: 0
LoadSceneTimeOut: 120
SpawnTimeout: 1
EnableNetworkLogs: 1
--- !u!114 &1765689956051871792
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5481270937743757918}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 6960e84d07fb87f47956e7a81d71c4e6, type: 3}
m_Name:
m_EditorClassIdentifier:
m_ProtocolType: 1
m_MaxPacketQueueSize: 512
m_MaxPayloadSize: 6144
m_MaxSendQueueSize: 98304
m_HeartbeatTimeoutMS: 500
m_ConnectTimeoutMS: 1000
m_MaxConnectAttempts: 60
m_DisconnectTimeoutMS: 30000
ConnectionData:
Address: 127.0.0.1
Port: 7777
ServerListenAddress:
DebugSimulator:
PacketDelayMS: 0
PacketJitterMS: 0
PacketDropRate: 0

7
Assets/Prefabs/NGO/NetworkManager.prefab.meta


fileFormatVersion: 2
guid: b963f71e4874d4066bc72b9224e3ffce
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

27
Assets/Scripts/GameLobby/Tests/PlayMode/AsyncTestHelper.cs


using System;
using System.Collections;
using System.Threading.Tasks;
namespace Test.Tools
{
public class AsyncTestHelper
{
public static IEnumerator Await(Task task)
{
while (!task.IsCompleted)
{
yield return null;
}
if (task.IsFaulted)
{
throw task.Exception;
}
}
public static IEnumerator Await(Func<Task> taskDelegate)
{
return Await(taskDelegate.Invoke());
}
}
}

11
Assets/Scripts/GameLobby/Tests/PlayMode/AsyncTestHelper.cs.meta


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

27
Assets/UniversalRenderPipelineGlobalSettings.asset


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2ec995e51a6e251468d2a3fd8a686257, type: 3}
m_Name: UniversalRenderPipelineGlobalSettings
m_EditorClassIdentifier:
k_AssetVersion: 2
lightLayerName0: Light Layer default
lightLayerName1: Light Layer 1
lightLayerName2: Light Layer 2
lightLayerName3: Light Layer 3
lightLayerName4: Light Layer 4
lightLayerName5: Light Layer 5
lightLayerName6: Light Layer 6
lightLayerName7: Light Layer 7
m_StripDebugVariants: 1
m_StripUnusedPostProcessingVariants: 0
m_StripUnusedVariants: 1
supportRuntimeDebugDisplay: 0

8
Assets/UniversalRenderPipelineGlobalSettings.asset.meta


fileFormatVersion: 2
guid: c96e53b1d712ac24eaccfd7f849c709d
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

15
ProjectSettings/RiderScriptEditorPersistedState.asset


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &1
MonoBehaviour:
m_ObjectHideFlags: 61
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 0}
m_Name:
m_EditorClassIdentifier: Unity.Rider.Editor:Packages.Rider.Editor:RiderScriptEditorPersistedState
lastWriteTicks: -8585486268141277427

16
ProjectSettings/ShaderGraphSettings.asset


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &1
MonoBehaviour:
m_ObjectHideFlags: 61
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: de02f9e1d18f588468e474319d09a723, type: 3}
m_Name:
m_EditorClassIdentifier:
customInterpolatorErrorThreshold: 32
customInterpolatorWarningThreshold: 16
正在加载...
取消
保存