Bind online session browser to canvas, drop IMGUI
- OnlineSessionManager: remove OnGUI/IMGUI state; now a logic-only layer exposing Host/Refresh/Join/Disconnect plus Status/IsBusy/IsConnected/ InSession/Sessions and Changed/SessionsChanged events - OnlineSessionBrowserUI (new): drives the Servers canvas — 4 buttons, session list from Entry Template clones (name + players), row selection, state-driven interactability, status footer - Main scene: attach binder, add status footer line, wire 8 refs; dev bootstrap panel disabled - Online Session Manager.prefab (new) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
286473930a
commit
d27ee16004
6 files changed
+3135
-85
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 940219f29a5971947be1767af2ec5a71
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+667
-2
@@ -380,7 +380,7 @@ MonoBehaviour:
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 284910513}
|
||||
m_Enabled: 1
|
||||
m_Enabled: 0
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 519095f0598dfdf4ebe457561f77771c, type: 3}
|
||||
m_Name:
|
||||
@@ -508,7 +508,6 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::OnlineSessionManager
|
||||
maxPlayers: 8
|
||||
showGui: 1
|
||||
--- !u!1 &330585543
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -679,6 +678,11 @@ MonoBehaviour:
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
CustomBlends: {fileID: 11400000, guid: 47b57a7fe51fd154e975311ad293878a, type: 2}
|
||||
--- !u!224 &499812163 stripped
|
||||
RectTransform:
|
||||
m_CorrespondingSourceObject: {fileID: 4566662197198005404, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
m_PrefabInstance: {fileID: 8599056809828915506}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!134 &539493728
|
||||
PhysicsMaterial:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -790,6 +794,60 @@ Transform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &617908208 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 1040229641786897100, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
m_PrefabInstance: {fileID: 8599056809828915506}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!114 &617908213
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 617908208}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c001d18ade3f180488179878fbaa3eef, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::OnlineSessionBrowserUI
|
||||
manager: {fileID: 284910519}
|
||||
hostButton: {fileID: 701418504}
|
||||
refreshButton: {fileID: 720768557}
|
||||
joinButton: {fileID: 1513726973}
|
||||
disconnectButton: {fileID: 1533948977}
|
||||
listContent: {fileID: 764069389}
|
||||
entryTemplate: {fileID: 1675823052}
|
||||
statusLabel: {fileID: 2102676159}
|
||||
selectedTint: {r: 0.26, g: 0.52, b: 0.96, a: 1}
|
||||
normalTint: {r: 1, g: 1, b: 1, a: 0.05}
|
||||
--- !u!114 &701418504 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 332368659673903902, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
m_PrefabInstance: {fileID: 8599056809828915506}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Button
|
||||
--- !u!114 &720768557 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 5436849756111560038, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
m_PrefabInstance: {fileID: 8599056809828915506}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Button
|
||||
--- !u!224 &764069389 stripped
|
||||
RectTransform:
|
||||
m_CorrespondingSourceObject: {fileID: 7674829218332492974, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
m_PrefabInstance: {fileID: 8599056809828915506}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1 &1282734303
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -914,6 +972,17 @@ Transform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &1513726973 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 4541850472183322180, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
m_PrefabInstance: {fileID: 8599056809828915506}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Button
|
||||
--- !u!1 &1516578026
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -965,6 +1034,210 @@ Transform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &1533948977 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 1380431663078587854, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
m_PrefabInstance: {fileID: 8599056809828915506}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Button
|
||||
--- !u!1 &1675823052 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 5933971478025665337, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
m_PrefabInstance: {fileID: 8599056809828915506}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!21 &1752619484
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: arialroundedmtprocyr_bold Atlas Material (Instance)
|
||||
m_Shader: {fileID: 4800000, guid: 68e6db2ebdc24f95958faec2be5558d6, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _Cube:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _FaceTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2664084111089754775, guid: 964ae5cd392ba08499b88de012ff8213, type: 2}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OutlineTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _Ambient: 0.5
|
||||
- _Bevel: 0.5
|
||||
- _BevelClamp: 0
|
||||
- _BevelOffset: 0
|
||||
- _BevelRoundness: 0
|
||||
- _BevelWidth: 0
|
||||
- _BumpFace: 0
|
||||
- _BumpOutline: 0
|
||||
- _ColorMask: 15
|
||||
- _CullMode: 0
|
||||
- _Diffuse: 0.5
|
||||
- _FaceDilate: 0
|
||||
- _FaceUVSpeedX: 0
|
||||
- _FaceUVSpeedY: 0
|
||||
- _GlowInner: 0.05
|
||||
- _GlowOffset: 0
|
||||
- _GlowOuter: 0.05
|
||||
- _GlowPower: 0.75
|
||||
- _GradientScale: 15
|
||||
- _LightAngle: 3.1416
|
||||
- _MaskSoftnessX: 0
|
||||
- _MaskSoftnessY: 0
|
||||
- _OutlineSoftness: 0
|
||||
- _OutlineUVSpeedX: 0
|
||||
- _OutlineUVSpeedY: 0
|
||||
- _OutlineWidth: 0
|
||||
- _PerspectiveFilter: 0.875
|
||||
- _Reflectivity: 10
|
||||
- _ScaleRatioA: 0.93333334
|
||||
- _ScaleRatioB: 0.7583333
|
||||
- _ScaleRatioC: 0.7583333
|
||||
- _ScaleX: 1
|
||||
- _ScaleY: 1
|
||||
- _ShaderFlags: 0
|
||||
- _Sharpness: 0
|
||||
- _SpecularPower: 2
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _TextureHeight: 2048
|
||||
- _TextureWidth: 2048
|
||||
- _UnderlayDilate: 0
|
||||
- _UnderlayOffsetX: 0
|
||||
- _UnderlayOffsetY: 0
|
||||
- _UnderlaySoftness: 0
|
||||
- _VertexOffsetX: 0
|
||||
- _VertexOffsetY: 0
|
||||
- _WeightBold: 0.75
|
||||
- _WeightNormal: 0
|
||||
m_Colors:
|
||||
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||
- _EnvMatrixRotation: {r: 0, g: 0, b: 0, a: 0}
|
||||
- _FaceColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _GlowColor: {r: 0, g: 1, b: 0, a: 0.5}
|
||||
- _MaskCoord: {r: 0, g: 0, b: 32767, a: 32767}
|
||||
- _OutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _ReflectFaceColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _SpecularColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
--- !u!1 &1902289938
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1902289941}
|
||||
- component: {fileID: 1902289940}
|
||||
- component: {fileID: 1902289939}
|
||||
m_Layer: 0
|
||||
m_Name: EventSystem
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &1902289939
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1902289938}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.InputSystem::UnityEngine.InputSystem.UI.InputSystemUIInputModule
|
||||
m_SendPointerHoverToParent: 1
|
||||
m_MoveRepeatDelay: 0.5
|
||||
m_MoveRepeatRate: 0.1
|
||||
m_XRTrackingOrigin: {fileID: 0}
|
||||
m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_PointAction: {fileID: -1654692200621890270, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_MoveAction: {fileID: -8784545083839296357, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_SubmitAction: {fileID: 392368643174621059, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_CancelAction: {fileID: 7727032971491509709, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_LeftClickAction: {fileID: 3001919216989983466, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_MiddleClickAction: {fileID: -2185481485913320682, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_RightClickAction: {fileID: -4090225696740746782, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_ScrollWheelAction: {fileID: 6240969308177333660, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_TrackedDevicePositionAction: {fileID: 6564999863303420839, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_TrackedDeviceOrientationAction: {fileID: 7970375526676320489, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_DeselectOnBackgroundClick: 1
|
||||
m_PointerBehavior: 0
|
||||
m_CursorLockBehavior: 0
|
||||
m_ScrollDeltaPerTick: 6
|
||||
--- !u!114 &1902289940
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1902289938}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.EventSystems.EventSystem
|
||||
m_FirstSelected: {fileID: 0}
|
||||
m_sendNavigationEvents: 1
|
||||
m_DragThreshold: 10
|
||||
--- !u!4 &1902289941
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1902289938}
|
||||
serializedVersion: 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: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &2009475132
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -1062,6 +1335,396 @@ Transform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &2102676158
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2102676161}
|
||||
- component: {fileID: 2102676160}
|
||||
- component: {fileID: 2102676159}
|
||||
m_Layer: 0
|
||||
m_Name: Status
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &2102676159
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2102676158}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 0
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: Idle
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 964ae5cd392ba08499b88de012ff8213, type: 2}
|
||||
m_sharedMaterial: {fileID: 1752619484}
|
||||
m_fontSharedMaterials:
|
||||
- {fileID: 1752619484}
|
||||
m_fontMaterial: {fileID: 1752619484}
|
||||
m_fontMaterials:
|
||||
- {fileID: 1752619484}
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4293979115
|
||||
m_fontColor: {r: 0.92, g: 0.92, b: 0.94, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 15
|
||||
m_fontSizeBase: 15
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 8192
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_characterHorizontalScale: 1
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_TextWrappingMode: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!222 &2102676160
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2102676158}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!224 &2102676161
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2102676158}
|
||||
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: 499812163}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: -4}
|
||||
m_SizeDelta: {x: -16, y: 24}
|
||||
m_Pivot: {x: 0.5, y: 1}
|
||||
--- !u!1001 &8599056809828915506
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 458161408064890808, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 458161408064890808, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 458161408064890808, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 458161408064890808, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 458161408064890808, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 458161408064890808, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1040229641786897100, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: Online Session Manager
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1124549748001373863, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1124549748001373863, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1124549748001373863, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1124549748001373863, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1124549748001373863, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1124549748001373863, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2926165666280585152, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2926165666280585152, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2926165666280585152, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2926165666280585152, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2926165666280585152, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2926165666280585152, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5909552448207580712, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5909552448207580712, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5909552448207580712, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5909552448207580712, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5909552448207580712, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5909552448207580712, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_Pivot.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_Pivot.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMax.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMin.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6044857652494613829, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7674829218332492974, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8110497960478258844, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_fontMaterial
|
||||
value:
|
||||
objectReference: {fileID: 1752619484}
|
||||
- target: {fileID: 8110497960478258844, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_sharedMaterial
|
||||
value:
|
||||
objectReference: {fileID: 1752619484}
|
||||
- target: {fileID: 8110497960478258844, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_fontMaterials.Array.size
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8110497960478258844, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: 'm_fontMaterials.Array.data[0]'
|
||||
value:
|
||||
objectReference: {fileID: 1752619484}
|
||||
- target: {fileID: 8110497960478258844, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_fontSharedMaterials.Array.size
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8110497960478258844, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: 'm_fontSharedMaterials.Array.data[0]'
|
||||
value:
|
||||
objectReference: {fileID: 1752619484}
|
||||
- target: {fileID: 8555406533395562537, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8555406533395562537, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8555406533395562537, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8555406533395562537, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8555406533395562537, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8555406533395562537, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects:
|
||||
- targetCorrespondingSourceObject: {fileID: 4566662197198005404, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 2102676161}
|
||||
m_AddedComponents:
|
||||
- targetCorrespondingSourceObject: {fileID: 1040229641786897100, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 617908213}
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 940219f29a5971947be1767af2ec5a71, type: 3}
|
||||
--- !u!1660057539 &9223372036854775807
|
||||
SceneRoots:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -1074,3 +1737,5 @@ SceneRoots:
|
||||
- {fileID: 1282734307}
|
||||
- {fileID: 2025317892}
|
||||
- {fileID: 284910517}
|
||||
- {fileID: 8599056809828915506}
|
||||
- {fileID: 1902289941}
|
||||
@@ -0,0 +1,168 @@
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// uGUI binding for <see cref="OnlineSessionManager"/>. Drives the server-browser canvas - Host / Refresh /
|
||||
/// pick a row / Join / Disconnect plus a status line - and mirrors the manager's state through its
|
||||
/// <see cref="OnlineSessionManager.Changed"/> / <see cref="OnlineSessionManager.SessionsChanged"/> events.
|
||||
/// Replaces the old IMGUI browser. Lives on the browser canvas; the session logic stays on the
|
||||
/// NetworkManager's <see cref="OnlineSessionManager"/>.
|
||||
///
|
||||
/// Selection model: Refresh fills the list with clones of <see cref="entryTemplate"/> (each a clickable row
|
||||
/// showing name + player count). Clicking a row selects it; Join connects to the selected session. While
|
||||
/// connected, only Disconnect is interactable.
|
||||
/// </summary>
|
||||
public class OnlineSessionBrowserUI : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private OnlineSessionManager manager;
|
||||
|
||||
[Header("Buttons")]
|
||||
[SerializeField] private Button hostButton;
|
||||
[SerializeField] private Button refreshButton;
|
||||
[SerializeField] private Button joinButton;
|
||||
[SerializeField] private Button disconnectButton;
|
||||
|
||||
[Header("List")]
|
||||
[Tooltip("Content RectTransform of the session ScrollRect (rows are added here).")]
|
||||
[SerializeField] private RectTransform listContent;
|
||||
[Tooltip("A row prototype kept disabled; cloned once per session. Children named 'Name' and 'Players' carry the text.")]
|
||||
[SerializeField] private GameObject entryTemplate;
|
||||
|
||||
[Header("Status")]
|
||||
[SerializeField] private TMP_Text statusLabel;
|
||||
|
||||
[Tooltip("Background tint of the selected row.")]
|
||||
[SerializeField] private Color selectedTint = new Color(0.26f, 0.52f, 0.96f, 1f);
|
||||
[Tooltip("Background tint of an unselected row.")]
|
||||
[SerializeField] private Color normalTint = new Color(1f, 1f, 1f, 0.05f);
|
||||
|
||||
private struct Row { public string id; public Image image; public GameObject go; }
|
||||
private readonly List<Row> _rows = new List<Row>();
|
||||
private string _selectedId;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// The template is the prototype, never shown itself - layout ignores it while disabled.
|
||||
if (entryTemplate) entryTemplate.SetActive(false);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (hostButton) hostButton.onClick.AddListener(OnHost);
|
||||
if (refreshButton) refreshButton.onClick.AddListener(OnRefresh);
|
||||
if (joinButton) joinButton.onClick.AddListener(OnJoin);
|
||||
if (disconnectButton) disconnectButton.onClick.AddListener(OnDisconnect);
|
||||
|
||||
if (manager)
|
||||
{
|
||||
manager.Changed += OnManagerChanged;
|
||||
manager.SessionsChanged += RebuildList;
|
||||
}
|
||||
|
||||
RebuildList();
|
||||
OnManagerChanged();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (hostButton) hostButton.onClick.RemoveListener(OnHost);
|
||||
if (refreshButton) refreshButton.onClick.RemoveListener(OnRefresh);
|
||||
if (joinButton) joinButton.onClick.RemoveListener(OnJoin);
|
||||
if (disconnectButton) disconnectButton.onClick.RemoveListener(OnDisconnect);
|
||||
|
||||
if (manager)
|
||||
{
|
||||
manager.Changed -= OnManagerChanged;
|
||||
manager.SessionsChanged -= RebuildList;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHost() { if (manager) manager.Host(); }
|
||||
private void OnRefresh() { if (manager) manager.Refresh(); }
|
||||
private void OnJoin() { if (manager && !string.IsNullOrEmpty(_selectedId)) manager.Join(_selectedId); }
|
||||
private void OnDisconnect() { if (manager) manager.Disconnect(); }
|
||||
|
||||
private void OnManagerChanged()
|
||||
{
|
||||
if (!manager) return;
|
||||
if (statusLabel) statusLabel.text = manager.Status;
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void UpdateButtons()
|
||||
{
|
||||
if (!manager) return;
|
||||
bool busy = manager.IsBusy;
|
||||
bool connected = manager.IsConnected;
|
||||
bool hasSelection = !string.IsNullOrEmpty(_selectedId);
|
||||
|
||||
if (hostButton) hostButton.interactable = !busy && !connected;
|
||||
if (refreshButton) refreshButton.interactable = !busy && !connected;
|
||||
if (joinButton) joinButton.interactable = !busy && !connected && hasSelection;
|
||||
if (disconnectButton) disconnectButton.interactable = !busy && connected;
|
||||
}
|
||||
|
||||
private void RebuildList()
|
||||
{
|
||||
for (int i = 0; i < _rows.Count; i++)
|
||||
if (_rows[i].go) Destroy(_rows[i].go);
|
||||
_rows.Clear();
|
||||
|
||||
if (manager && entryTemplate && listContent)
|
||||
{
|
||||
var sessions = manager.Sessions;
|
||||
bool selectionStillPresent = false;
|
||||
|
||||
for (int i = 0; i < sessions.Count; i++)
|
||||
{
|
||||
var s = sessions[i];
|
||||
var go = Instantiate(entryTemplate, listContent);
|
||||
go.SetActive(true);
|
||||
|
||||
var nameText = FindText(go.transform, "Name");
|
||||
if (nameText) nameText.text = s.Name;
|
||||
|
||||
var playersText = FindText(go.transform, "Players");
|
||||
if (playersText)
|
||||
{
|
||||
int taken = Mathf.Max(0, s.MaxPlayers - s.AvailableSlots);
|
||||
playersText.text = $"{taken}/{s.MaxPlayers}";
|
||||
}
|
||||
|
||||
string id = s.Id; // capture per-row for the click closure
|
||||
var button = go.GetComponent<Button>();
|
||||
if (button) button.onClick.AddListener(() => Select(id));
|
||||
|
||||
_rows.Add(new Row { id = id, image = go.GetComponent<Image>(), go = go });
|
||||
if (id == _selectedId) selectionStillPresent = true;
|
||||
}
|
||||
|
||||
if (!selectionStillPresent) _selectedId = null;
|
||||
}
|
||||
|
||||
ApplyTints();
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void Select(string id)
|
||||
{
|
||||
_selectedId = id;
|
||||
ApplyTints();
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void ApplyTints()
|
||||
{
|
||||
for (int i = 0; i < _rows.Count; i++)
|
||||
if (_rows[i].image)
|
||||
_rows[i].image.color = _rows[i].id == _selectedId ? selectedTint : normalTint;
|
||||
}
|
||||
|
||||
private static TMP_Text FindText(Transform root, string childName)
|
||||
{
|
||||
var t = root.Find(childName);
|
||||
return t ? t.GetComponent<TMP_Text>() : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c001d18ade3f180488179878fbaa3eef
|
||||
@@ -20,8 +20,9 @@ using UnityEngine;
|
||||
/// NetworkManager callbacks fire exactly as they do for loopback hosting, so MatchManager, spawning and
|
||||
/// authority are unaffected.
|
||||
///
|
||||
/// This is a quick IMGUI server browser for clone testing; replace with proper uGUI later. The loopback
|
||||
/// dev path (see <see cref="NetworkBootstrap"/>, H/C/J/K) stays for fast local testing - online is additive.
|
||||
/// This is the logic layer only: state + async host/refresh/join/disconnect calls, surfaced through the
|
||||
/// <see cref="Changed"/>/<see cref="SessionsChanged"/> events. The uGUI server browser that drives it lives
|
||||
/// on its own canvas (<see cref="OnlineSessionBrowserUI"/>); this component carries no UI of its own.
|
||||
/// Requires the project to be linked to a UGS cloud project (Project Settings > Services) with Relay,
|
||||
/// Lobby and Authentication (Anonymous) enabled; otherwise sign-in fails with a clear status message.
|
||||
/// Attach to the same GameObject as the NetworkManager.
|
||||
@@ -33,17 +34,26 @@ public class OnlineSessionManager : MonoBehaviour
|
||||
[Tooltip("Maximum players per hosted session (host included).")]
|
||||
public int maxPlayers = 8;
|
||||
|
||||
[Tooltip("Draw the on-screen online server-browser panel (below the dev panel).")]
|
||||
public bool showGui = true;
|
||||
|
||||
private NetworkManager _net;
|
||||
private ISession _session; // active session (host or client); null when not in one
|
||||
private IList<ISessionInfo> _browse = new List<ISessionInfo>();
|
||||
private List<ISessionInfo> _sessions = new List<ISessionInfo>();
|
||||
private string _hostName = "";
|
||||
private string _status = "Idle";
|
||||
private bool _busy;
|
||||
private bool _leaving; // suppress the defensive leave while an explicit leave is in flight
|
||||
private Vector2 _scroll;
|
||||
|
||||
/// <summary>Raised when status, busy state, or the connection state changes, so a bound UI can re-render.
|
||||
/// Async continuations resume on the main thread, so handlers run there.</summary>
|
||||
public event Action Changed;
|
||||
|
||||
/// <summary>Raised after the browsable session list is replaced (a refresh completed).</summary>
|
||||
public event Action SessionsChanged;
|
||||
|
||||
public string Status => _status;
|
||||
public bool IsBusy => _busy;
|
||||
public bool IsConnected => _net && _net.IsListening;
|
||||
public bool InSession => _session != null;
|
||||
public IReadOnlyList<ISessionInfo> Sessions => _sessions;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
@@ -54,6 +64,8 @@ public class OnlineSessionManager : MonoBehaviour
|
||||
private void OnEnable()
|
||||
{
|
||||
if (!_net) return;
|
||||
_net.OnServerStarted += OnNetworkStarted;
|
||||
_net.OnClientStarted += OnNetworkStarted;
|
||||
_net.OnServerStopped += OnNetworkStopped;
|
||||
_net.OnClientStopped += OnNetworkStopped;
|
||||
}
|
||||
@@ -61,10 +73,14 @@ public class OnlineSessionManager : MonoBehaviour
|
||||
private void OnDisable()
|
||||
{
|
||||
if (!_net) return;
|
||||
_net.OnServerStarted -= OnNetworkStarted;
|
||||
_net.OnClientStarted -= OnNetworkStarted;
|
||||
_net.OnServerStopped -= OnNetworkStopped;
|
||||
_net.OnClientStopped -= OnNetworkStopped;
|
||||
}
|
||||
|
||||
private void OnNetworkStarted() => Changed?.Invoke();
|
||||
|
||||
// The match-end / disconnect / Shutdown paths stop the NetworkManager without telling UGS. Leave the
|
||||
// session here too so the Relay allocation and the public lobby entry are released.
|
||||
private void OnNetworkStopped(bool _)
|
||||
@@ -72,6 +88,7 @@ public class OnlineSessionManager : MonoBehaviour
|
||||
var stale = _session;
|
||||
_session = null;
|
||||
if (stale != null && !_leaving) LeaveSilently(stale);
|
||||
Changed?.Invoke();
|
||||
}
|
||||
|
||||
private async void LeaveSilently(ISession session)
|
||||
@@ -80,6 +97,27 @@ public class OnlineSessionManager : MonoBehaviour
|
||||
catch (Exception e) { Debug.LogWarning($"[OnlineSession] leave-on-stop failed: {e.Message}"); }
|
||||
}
|
||||
|
||||
// ----- Public API (driven by OnlineSessionBrowserUI) -------------------------------------------------
|
||||
|
||||
public void Host() => HostAsync();
|
||||
public void Refresh() => RefreshAsync();
|
||||
public void Join(string sessionId) => JoinAsync(sessionId);
|
||||
public void Disconnect() => DisconnectAsync();
|
||||
|
||||
// ----- Implementation --------------------------------------------------------------------------------
|
||||
|
||||
private void SetStatus(string status)
|
||||
{
|
||||
_status = status;
|
||||
Changed?.Invoke();
|
||||
}
|
||||
|
||||
private void SetBusy(bool busy)
|
||||
{
|
||||
_busy = busy;
|
||||
Changed?.Invoke();
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task EnsureSignedInAsync()
|
||||
{
|
||||
if (UnityServices.State != ServicesInitializationState.Initialized)
|
||||
@@ -113,131 +151,100 @@ public class OnlineSessionManager : MonoBehaviour
|
||||
|
||||
private async void HostAsync()
|
||||
{
|
||||
if (_busy) return;
|
||||
_busy = true;
|
||||
if (_busy || IsConnected) return;
|
||||
SetBusy(true);
|
||||
try
|
||||
{
|
||||
_status = "Signing in…";
|
||||
SetStatus("Signing in…");
|
||||
await EnsureSignedInAsync();
|
||||
_status = "Creating session…";
|
||||
SetStatus("Creating session…");
|
||||
var options = new SessionOptions
|
||||
{
|
||||
Name = string.IsNullOrWhiteSpace(_hostName) ? "Chameleon game" : _hostName.Trim(),
|
||||
MaxPlayers = Mathf.Max(2, maxPlayers)
|
||||
}.WithRelayNetwork();
|
||||
_session = await MultiplayerService.Instance.CreateSessionAsync(options);
|
||||
_status = $"Hosting \"{_session.Name}\" (code {_session.Code})";
|
||||
SetStatus($"Hosting \"{_session.Name}\" (code {_session.Code})");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_status = $"Host failed: {e.Message}";
|
||||
SetStatus($"Host failed: {e.Message}");
|
||||
Debug.LogException(e);
|
||||
}
|
||||
finally { _busy = false; }
|
||||
finally { SetBusy(false); }
|
||||
}
|
||||
|
||||
private async void RefreshAsync()
|
||||
{
|
||||
if (_busy) return;
|
||||
_busy = true;
|
||||
SetBusy(true);
|
||||
try
|
||||
{
|
||||
_status = "Signing in…";
|
||||
SetStatus("Signing in…");
|
||||
await EnsureSignedInAsync();
|
||||
_status = "Querying sessions…";
|
||||
SetStatus("Querying sessions…");
|
||||
var results = await MultiplayerService.Instance.QuerySessionsAsync(new QuerySessionsOptions());
|
||||
_browse = results.Sessions;
|
||||
_status = $"{_browse.Count} session(s) found";
|
||||
_sessions = new List<ISessionInfo>(results.Sessions);
|
||||
SessionsChanged?.Invoke();
|
||||
SetStatus($"{_sessions.Count} session(s) found");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_status = $"Refresh failed: {e.Message}";
|
||||
SetStatus($"Refresh failed: {e.Message}");
|
||||
Debug.LogException(e);
|
||||
}
|
||||
finally { _busy = false; }
|
||||
finally { SetBusy(false); }
|
||||
}
|
||||
|
||||
private async void JoinAsync(string sessionId)
|
||||
{
|
||||
if (_busy) return;
|
||||
_busy = true;
|
||||
if (_busy || IsConnected || string.IsNullOrEmpty(sessionId)) return;
|
||||
SetBusy(true);
|
||||
try
|
||||
{
|
||||
_status = "Signing in…";
|
||||
SetStatus("Signing in…");
|
||||
await EnsureSignedInAsync();
|
||||
_status = "Joining session…";
|
||||
SetStatus("Joining session…");
|
||||
_session = await MultiplayerService.Instance.JoinSessionByIdAsync(sessionId);
|
||||
_status = $"Joined \"{_session.Name}\"";
|
||||
SetStatus($"Joined \"{_session.Name}\"");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_status = $"Join failed: {e.Message}";
|
||||
SetStatus($"Join failed: {e.Message}");
|
||||
Debug.LogException(e);
|
||||
}
|
||||
finally { _busy = false; }
|
||||
finally { SetBusy(false); }
|
||||
}
|
||||
|
||||
private async void LeaveAsync()
|
||||
private async void DisconnectAsync()
|
||||
{
|
||||
if (_busy || _session == null) return;
|
||||
_busy = true;
|
||||
_leaving = true;
|
||||
try
|
||||
if (_busy) return;
|
||||
|
||||
// A UGS session leaves cleanly (LeaveAsync also tears down the NGO connection). A plain loopback
|
||||
// host/client - if one is ever active without a session - just shuts the transport down.
|
||||
if (_session != null)
|
||||
{
|
||||
_status = "Leaving…";
|
||||
await _session.LeaveAsync(); // also tears down the NGO connection
|
||||
_status = "Left session";
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_status = $"Leave failed: {e.Message}";
|
||||
Debug.LogException(e);
|
||||
}
|
||||
finally { _session = null; _leaving = false; _busy = false; }
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (!showGui || !_net) return;
|
||||
|
||||
GUILayout.BeginArea(new Rect(10, 180, 340, 360), GUI.skin.box);
|
||||
GUILayout.Label("Online (UGS Relay + Lobby)");
|
||||
GUILayout.Label(_status);
|
||||
|
||||
GUI.enabled = !_busy;
|
||||
if (!_net.IsListening)
|
||||
{
|
||||
GUILayout.Label("Session name:");
|
||||
_hostName = GUILayout.TextField(_hostName);
|
||||
if (GUILayout.Button("Host Online")) HostAsync();
|
||||
|
||||
GUILayout.Space(6);
|
||||
if (GUILayout.Button("Refresh List")) RefreshAsync();
|
||||
|
||||
_scroll = GUILayout.BeginScrollView(_scroll, GUILayout.Height(180));
|
||||
if (_browse.Count == 0)
|
||||
GUILayout.Label("No sessions. Click Refresh.");
|
||||
foreach (var s in _browse)
|
||||
SetBusy(true);
|
||||
_leaving = true;
|
||||
var session = _session;
|
||||
_session = null;
|
||||
try
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
int taken = Mathf.Max(0, s.MaxPlayers - s.AvailableSlots);
|
||||
GUILayout.Label($"{s.Name} ({taken}/{s.MaxPlayers})");
|
||||
if (GUILayout.Button("Join", GUILayout.Width(60))) JoinAsync(s.Id);
|
||||
GUILayout.EndHorizontal();
|
||||
SetStatus("Leaving…");
|
||||
await session.LeaveAsync();
|
||||
SetStatus("Left session");
|
||||
}
|
||||
GUILayout.EndScrollView();
|
||||
catch (Exception e)
|
||||
{
|
||||
SetStatus($"Leave failed: {e.Message}");
|
||||
Debug.LogException(e);
|
||||
}
|
||||
finally { _leaving = false; SetBusy(false); }
|
||||
}
|
||||
else if (_session != null)
|
||||
else if (IsConnected)
|
||||
{
|
||||
GUILayout.Label($"In session: {_session.Name}");
|
||||
if (GUILayout.Button("Leave Session")) LeaveAsync();
|
||||
_net.Shutdown();
|
||||
SetStatus("Disconnected");
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label("Local (loopback) session active.");
|
||||
}
|
||||
GUI.enabled = true;
|
||||
|
||||
GUILayout.EndArea();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user