aha
This commit is contained in:
8
Assets/Mirror/Examples/MultipleMatches/Prefabs.meta
Normal file
8
Assets/Mirror/Examples/MultipleMatches/Prefabs.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad2253a5702ed854995bf034be09a1ae
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
149
Assets/Mirror/Examples/MultipleMatches/Prefabs/CellGUI.prefab
Normal file
149
Assets/Mirror/Examples/MultipleMatches/Prefabs/CellGUI.prefab
Normal file
@ -0,0 +1,149 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &4903779300334215825
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8667093524748208693}
|
||||
- component: {fileID: 792638734159983555}
|
||||
- component: {fileID: 2985632515421915780}
|
||||
- component: {fileID: 9218727033388977555}
|
||||
- component: {fileID: 2439948753870522382}
|
||||
m_Layer: 5
|
||||
m_Name: CellGUI
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &8667093524748208693
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4903779300334215825}
|
||||
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_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &792638734159983555
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4903779300334215825}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!114 &2985632515421915780
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4903779300334215825}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 0}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &9218727033388977555
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4903779300334215825}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Highlighted
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 2985632515421915780}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls:
|
||||
- m_Target: {fileID: 2439948753870522382}
|
||||
m_MethodName: MakePlay
|
||||
m_Mode: 1
|
||||
m_Arguments:
|
||||
m_ObjectArgument: {fileID: 0}
|
||||
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
|
||||
m_IntArgument: 0
|
||||
m_FloatArgument: 0
|
||||
m_StringArgument:
|
||||
m_BoolArgument: 0
|
||||
m_CallState: 2
|
||||
--- !u!114 &2439948753870522382
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4903779300334215825}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9cda2a394a443474689a3c6d6044f7b0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
matchController: {fileID: 0}
|
||||
cellValue: 0
|
||||
image: {fileID: 2985632515421915780}
|
||||
button: {fileID: 9218727033388977555}
|
||||
playerIdentity: {fileID: 0}
|
@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ab8c221183f0094eb04b7f6eb569e7b
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Prefabs/CellGUI.prefab
|
||||
uploadId: 736421
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e101d385946c91b4c81f318efc723a88
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Prefabs/MatchController.prefab
|
||||
uploadId: 736421
|
311
Assets/Mirror/Examples/MultipleMatches/Prefabs/MatchGUI.prefab
Normal file
311
Assets/Mirror/Examples/MultipleMatches/Prefabs/MatchGUI.prefab
Normal file
@ -0,0 +1,311 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &732536732566260629
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 6013388882030083517}
|
||||
- component: {fileID: 2895310434674857523}
|
||||
- component: {fileID: 7191823870515597218}
|
||||
m_Layer: 5
|
||||
m_Name: Players
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &6013388882030083517
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 732536732566260629}
|
||||
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_Children: []
|
||||
m_Father: {fileID: 3533216216399874122}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 1, y: 0.5}
|
||||
m_AnchorMax: {x: 1, y: 0.5}
|
||||
m_AnchoredPosition: {x: -10, y: 0}
|
||||
m_SizeDelta: {x: 60, y: 30}
|
||||
m_Pivot: {x: 1, y: 0.5}
|
||||
--- !u!222 &2895310434674857523
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 732536732566260629}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!114 &7191823870515597218
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 732536732566260629}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 0.78431374}
|
||||
m_RaycastTarget: 1
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_FontSize: 20
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 2
|
||||
m_MaxSize: 40
|
||||
m_Alignment: 5
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: X / X
|
||||
--- !u!1 &3533216216399874123
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3533216216399874122}
|
||||
- component: {fileID: 3533216216399874119}
|
||||
- component: {fileID: 8159776287394259959}
|
||||
- component: {fileID: 8871144159682159596}
|
||||
- component: {fileID: 114572912279416540}
|
||||
m_Layer: 5
|
||||
m_Name: MatchGUI
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &3533216216399874122
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3533216216399874123}
|
||||
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_Children:
|
||||
- {fileID: 8536989563668766087}
|
||||
- {fileID: 6013388882030083517}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 30}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &3533216216399874119
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3533216216399874123}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!114 &8159776287394259959
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3533216216399874123}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 0.19607843}
|
||||
m_RaycastTarget: 1
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 0}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &8871144159682159596
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3533216216399874123}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Highlighted
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 8159776287394259959}
|
||||
toggleTransition: 1
|
||||
graphic: {fileID: 0}
|
||||
m_Group: {fileID: 0}
|
||||
onValueChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls:
|
||||
- m_Target: {fileID: 114572912279416540}
|
||||
m_MethodName: OnToggleClicked
|
||||
m_Mode: 0
|
||||
m_Arguments:
|
||||
m_ObjectArgument: {fileID: 0}
|
||||
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
|
||||
m_IntArgument: 0
|
||||
m_FloatArgument: 0
|
||||
m_StringArgument:
|
||||
m_BoolArgument: 0
|
||||
m_CallState: 2
|
||||
m_IsOn: 0
|
||||
--- !u!114 &114572912279416540
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3533216216399874123}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: e875a237ce12c3145b20f17222f10b68, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
image: {fileID: 8159776287394259959}
|
||||
toggleButton: {fileID: 8871144159682159596}
|
||||
matchName: {fileID: 4525608779212400833}
|
||||
playerCount: {fileID: 7191823870515597218}
|
||||
canvasController: {fileID: 0}
|
||||
--- !u!1 &5341423849544309394
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8536989563668766087}
|
||||
- component: {fileID: 3979716480785526962}
|
||||
- component: {fileID: 4525608779212400833}
|
||||
m_Layer: 5
|
||||
m_Name: Name
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &8536989563668766087
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5341423849544309394}
|
||||
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_Children: []
|
||||
m_Father: {fileID: 3533216216399874122}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0.5}
|
||||
m_AnchorMax: {x: 0, y: 0.5}
|
||||
m_AnchoredPosition: {x: 10, y: 0}
|
||||
m_SizeDelta: {x: 200, y: 30}
|
||||
m_Pivot: {x: 0, y: 0.5}
|
||||
--- !u!222 &3979716480785526962
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5341423849544309394}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!114 &4525608779212400833
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5341423849544309394}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 0.78431374}
|
||||
m_RaycastTarget: 1
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_FontSize: 20
|
||||
m_FontStyle: 1
|
||||
m_BestFit: 0
|
||||
m_MinSize: 2
|
||||
m_MaxSize: 40
|
||||
m_Alignment: 4
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: Match X
|
@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df3727c2222378b4ca786485a8b09981
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Prefabs/MatchGUI.prefab
|
||||
uploadId: 736421
|
@ -0,0 +1,67 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &3559083313143303799
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1204658229548937417}
|
||||
- component: {fileID: 7660209086417859164}
|
||||
- component: {fileID: -3992624706284245286}
|
||||
m_Layer: 0
|
||||
m_Name: MatchPlayer
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &1204658229548937417
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3559083313143303799}
|
||||
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_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &7660209086417859164
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3559083313143303799}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
sceneId: 0
|
||||
_assetId: 3049278420
|
||||
serverOnly: 0
|
||||
visibility: 0
|
||||
hasSpawned: 0
|
||||
--- !u!114 &-3992624706284245286
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3559083313143303799}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5d17e718851449a6879986e45c458fb7, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
syncDirection: 0
|
||||
syncMode: 0
|
||||
syncInterval: 0.1
|
||||
MatchID:
|
@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11d2414f1e120a14c98cba6866e5348f
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Prefabs/MatchPlayer.prefab
|
||||
uploadId: 736421
|
185
Assets/Mirror/Examples/MultipleMatches/Prefabs/PlayerGUI.prefab
Normal file
185
Assets/Mirror/Examples/MultipleMatches/Prefabs/PlayerGUI.prefab
Normal file
@ -0,0 +1,185 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &2742256683483721700
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4805460816392144898}
|
||||
- component: {fileID: 4240234839557606510}
|
||||
- component: {fileID: 733636089880751452}
|
||||
- component: {fileID: 8081368318735942264}
|
||||
m_Layer: 5
|
||||
m_Name: PlayerGUI
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4805460816392144898
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2742256683483721700}
|
||||
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_Children:
|
||||
- {fileID: 4975002542353798605}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 50}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &4240234839557606510
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2742256683483721700}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!114 &733636089880751452
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2742256683483721700}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0.2509804, g: 0.2509804, b: 0.2509804, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 0}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &8081368318735942264
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2742256683483721700}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f61e9bc3715eb904b91222a5526f63d8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
playerName: {fileID: 893070459539714110}
|
||||
--- !u!1 &4667088617155248724
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4975002542353798605}
|
||||
- component: {fileID: 8874787277914191185}
|
||||
- component: {fileID: 893070459539714110}
|
||||
- component: {fileID: 1559385578385937998}
|
||||
m_Layer: 5
|
||||
m_Name: Text
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4975002542353798605
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4667088617155248724}
|
||||
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_Children: []
|
||||
m_Father: {fileID: 4805460816392144898}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 300, y: 50}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &8874787277914191185
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4667088617155248724}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!114 &893070459539714110
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4667088617155248724}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_FontSize: 25
|
||||
m_FontStyle: 1
|
||||
m_BestFit: 0
|
||||
m_MinSize: 0
|
||||
m_MaxSize: 40
|
||||
m_Alignment: 4
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: Player X
|
||||
--- !u!114 &1559385578385937998
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4667088617155248724}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: e19747de3f5aca642ab2be37e372fb86, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_EffectColor: {r: 0, g: 0, b: 0, a: 0.5}
|
||||
m_EffectDistance: {x: 1, y: -1}
|
||||
m_UseGraphicAlpha: 1
|
@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 504f86497324bc040be44f6f88b6cc73
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Prefabs/PlayerGUI.prefab
|
||||
uploadId: 736421
|
9
Assets/Mirror/Examples/MultipleMatches/README.md
Normal file
9
Assets/Mirror/Examples/MultipleMatches/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# MultipleMatches Example
|
||||
|
||||
This example demonstrates how to run a large number of non-physics games concurrently in a single game server instance.
|
||||
|
||||
This would be most appropriate for Card, Board, Puzzle, and Arcade games where there is no physics involved, just presentation and messaging.
|
||||
|
||||
While this example is turn-based, real-time games work just as well.
|
||||
|
||||
When a match is started, a MatchController and Player objects are spawned, all with a Network Match Checker component with the same matchId set. Only clients with the same matchID get messages about each others actions and about their own match. They don't receive any data about other matches that may be running concurrently.
|
14
Assets/Mirror/Examples/MultipleMatches/README.md.meta
Normal file
14
Assets/Mirror/Examples/MultipleMatches/README.md.meta
Normal file
@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9749e23e4e90e0646afc81061710a927
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/README.md
|
||||
uploadId: 736421
|
8
Assets/Mirror/Examples/MultipleMatches/Scenes.meta
Normal file
8
Assets/Mirror/Examples/MultipleMatches/Scenes.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a92fd9255da5fe9449e612566195a3aa
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa1f875396fa7d348a782cebc2f75d7c
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Scenes/MirrorMultipleMatches.unity
|
||||
uploadId: 736421
|
8
Assets/Mirror/Examples/MultipleMatches/Scripts.meta
Normal file
8
Assets/Mirror/Examples/MultipleMatches/Scripts.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d418be768b6d32e4d9c3b8828929c3eb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,644 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Mirror.Examples.MultipleMatch
|
||||
{
|
||||
public class CanvasController : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Match Controllers listen for this to terminate their match and clean up
|
||||
/// </summary>
|
||||
public event Action<NetworkConnectionToClient> OnPlayerDisconnect;
|
||||
|
||||
/// <summary>
|
||||
/// Cross-reference of client that created the corresponding match in openMatches below
|
||||
/// </summary>
|
||||
internal static readonly Dictionary<NetworkConnectionToClient, Guid> playerMatches = new Dictionary<NetworkConnectionToClient, Guid>();
|
||||
|
||||
/// <summary>
|
||||
/// Open matches that are available for joining
|
||||
/// </summary>
|
||||
internal static readonly Dictionary<Guid, MatchInfo> openMatches = new Dictionary<Guid, MatchInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// Network Connections of all players in a match
|
||||
/// </summary>
|
||||
internal static readonly Dictionary<Guid, HashSet<NetworkConnectionToClient>> matchConnections = new Dictionary<Guid, HashSet<NetworkConnectionToClient>>();
|
||||
|
||||
/// <summary>
|
||||
/// Player informations by Network Connection
|
||||
/// </summary>
|
||||
internal static readonly Dictionary<NetworkConnectionToClient, PlayerInfo> playerInfos = new Dictionary<NetworkConnectionToClient, PlayerInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// Network Connections that have neither started nor joined a match yet
|
||||
/// </summary>
|
||||
internal static readonly List<NetworkConnectionToClient> waitingConnections = new List<NetworkConnectionToClient>();
|
||||
|
||||
/// <summary>
|
||||
/// GUID of a match the local player has created
|
||||
/// </summary>
|
||||
internal Guid localPlayerMatch = Guid.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// GUID of a match the local player has joined
|
||||
/// </summary>
|
||||
internal Guid localJoinedMatch = Guid.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// GUID of a match the local player has selected in the Toggle Group match list
|
||||
/// </summary>
|
||||
internal Guid selectedMatch = Guid.Empty;
|
||||
|
||||
// Used in UI for "Player #"
|
||||
int playerIndex = 1;
|
||||
|
||||
[Header("GUI References")]
|
||||
public GameObject matchList;
|
||||
public GameObject matchPrefab;
|
||||
public GameObject matchControllerPrefab;
|
||||
public Button createButton;
|
||||
public Button joinButton;
|
||||
public GameObject lobbyView;
|
||||
public GameObject roomView;
|
||||
public RoomGUI roomGUI;
|
||||
public ToggleGroup toggleGroup;
|
||||
|
||||
// RuntimeInitializeOnLoadMethod -> fast playmode without domain reload
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
static void ResetStatics()
|
||||
{
|
||||
playerMatches.Clear();
|
||||
openMatches.Clear();
|
||||
matchConnections.Clear();
|
||||
playerInfos.Clear();
|
||||
waitingConnections.Clear();
|
||||
}
|
||||
|
||||
#region UI Functions
|
||||
|
||||
// Called from several places to ensure a clean reset
|
||||
// - MatchNetworkManager.Awake
|
||||
// - OnStartServer
|
||||
// - OnStartClient
|
||||
// - OnClientDisconnect
|
||||
// - ResetCanvas
|
||||
internal void InitializeData()
|
||||
{
|
||||
playerMatches.Clear();
|
||||
openMatches.Clear();
|
||||
matchConnections.Clear();
|
||||
waitingConnections.Clear();
|
||||
localPlayerMatch = Guid.Empty;
|
||||
localJoinedMatch = Guid.Empty;
|
||||
}
|
||||
|
||||
// Called from OnStopServer and OnStopClient when shutting down
|
||||
void ResetCanvas()
|
||||
{
|
||||
InitializeData();
|
||||
lobbyView.SetActive(false);
|
||||
roomView.SetActive(false);
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Button Calls
|
||||
|
||||
/// <summary>
|
||||
/// Called from <see cref="MatchGUI.OnToggleClicked"/>
|
||||
/// </summary>
|
||||
/// <param name="matchId"></param>
|
||||
[ClientCallback]
|
||||
public void SelectMatch(Guid matchId)
|
||||
{
|
||||
if (matchId == Guid.Empty)
|
||||
{
|
||||
selectedMatch = Guid.Empty;
|
||||
joinButton.interactable = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!openMatches.Keys.Contains(matchId))
|
||||
{
|
||||
joinButton.interactable = false;
|
||||
return;
|
||||
}
|
||||
|
||||
selectedMatch = matchId;
|
||||
MatchInfo infos = openMatches[matchId];
|
||||
joinButton.interactable = infos.players < infos.maxPlayers;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigned in inspector to Create button
|
||||
/// </summary>
|
||||
[ClientCallback]
|
||||
public void RequestCreateMatch()
|
||||
{
|
||||
NetworkClient.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Create });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigned in inspector to Cancel button
|
||||
/// </summary>
|
||||
[ClientCallback]
|
||||
public void RequestCancelMatch()
|
||||
{
|
||||
if (localPlayerMatch == Guid.Empty) return;
|
||||
|
||||
NetworkClient.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Cancel });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigned in inspector to Join button
|
||||
/// </summary>
|
||||
[ClientCallback]
|
||||
public void RequestJoinMatch()
|
||||
{
|
||||
if (selectedMatch == Guid.Empty) return;
|
||||
|
||||
NetworkClient.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Join, matchId = selectedMatch });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigned in inspector to Leave button
|
||||
/// </summary>
|
||||
[ClientCallback]
|
||||
public void RequestLeaveMatch()
|
||||
{
|
||||
if (localJoinedMatch == Guid.Empty) return;
|
||||
|
||||
NetworkClient.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Leave, matchId = localJoinedMatch });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigned in inspector to Ready button
|
||||
/// </summary>
|
||||
[ClientCallback]
|
||||
public void RequestReadyChange()
|
||||
{
|
||||
if (localPlayerMatch == Guid.Empty && localJoinedMatch == Guid.Empty) return;
|
||||
|
||||
Guid matchId = localPlayerMatch == Guid.Empty ? localJoinedMatch : localPlayerMatch;
|
||||
|
||||
NetworkClient.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Ready, matchId = matchId });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigned in inspector to Start button
|
||||
/// </summary>
|
||||
[ClientCallback]
|
||||
public void RequestStartMatch()
|
||||
{
|
||||
if (localPlayerMatch == Guid.Empty) return;
|
||||
|
||||
NetworkClient.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Start });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called from <see cref="MatchController.RpcExitGame"/>
|
||||
/// </summary>
|
||||
[ClientCallback]
|
||||
public void OnMatchEnded()
|
||||
{
|
||||
localPlayerMatch = Guid.Empty;
|
||||
localJoinedMatch = Guid.Empty;
|
||||
ShowLobbyView();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Server & Client Callbacks
|
||||
|
||||
// Methods in this section are called from MatchNetworkManager's corresponding methods
|
||||
|
||||
[ServerCallback]
|
||||
internal void OnStartServer()
|
||||
{
|
||||
InitializeData();
|
||||
NetworkServer.RegisterHandler<ServerMatchMessage>(OnServerMatchMessage);
|
||||
}
|
||||
|
||||
[ServerCallback]
|
||||
internal void OnServerReady(NetworkConnectionToClient conn)
|
||||
{
|
||||
waitingConnections.Add(conn);
|
||||
playerInfos.Add(conn, new PlayerInfo { playerIndex = this.playerIndex, ready = false });
|
||||
playerIndex++;
|
||||
|
||||
SendMatchList();
|
||||
}
|
||||
|
||||
[ServerCallback]
|
||||
internal IEnumerator OnServerDisconnect(NetworkConnectionToClient conn)
|
||||
{
|
||||
// Invoke OnPlayerDisconnect on all instances of MatchController
|
||||
OnPlayerDisconnect?.Invoke(conn);
|
||||
|
||||
if (playerMatches.TryGetValue(conn, out Guid matchId))
|
||||
{
|
||||
playerMatches.Remove(conn);
|
||||
openMatches.Remove(matchId);
|
||||
|
||||
foreach (NetworkConnectionToClient playerConn in matchConnections[matchId])
|
||||
{
|
||||
PlayerInfo _playerInfo = playerInfos[playerConn];
|
||||
_playerInfo.ready = false;
|
||||
_playerInfo.matchId = Guid.Empty;
|
||||
playerInfos[playerConn] = _playerInfo;
|
||||
playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Departed });
|
||||
}
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<Guid, HashSet<NetworkConnectionToClient>> kvp in matchConnections)
|
||||
kvp.Value.Remove(conn);
|
||||
|
||||
PlayerInfo playerInfo = playerInfos[conn];
|
||||
if (playerInfo.matchId != Guid.Empty)
|
||||
{
|
||||
if (openMatches.TryGetValue(playerInfo.matchId, out MatchInfo matchInfo))
|
||||
{
|
||||
matchInfo.players--;
|
||||
openMatches[playerInfo.matchId] = matchInfo;
|
||||
}
|
||||
|
||||
HashSet<NetworkConnectionToClient> connections;
|
||||
if (matchConnections.TryGetValue(playerInfo.matchId, out connections))
|
||||
{
|
||||
PlayerInfo[] infos = connections.Select(playerConn => playerInfos[playerConn]).ToArray();
|
||||
|
||||
foreach (NetworkConnectionToClient playerConn in matchConnections[playerInfo.matchId])
|
||||
if (playerConn != conn)
|
||||
playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.UpdateRoom, playerInfos = infos });
|
||||
}
|
||||
}
|
||||
|
||||
SendMatchList();
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
[ServerCallback]
|
||||
internal void OnStopServer()
|
||||
{
|
||||
ResetCanvas();
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
internal void OnStartClient()
|
||||
{
|
||||
InitializeData();
|
||||
ShowLobbyView();
|
||||
createButton.gameObject.SetActive(true);
|
||||
joinButton.gameObject.SetActive(true);
|
||||
NetworkClient.RegisterHandler<ClientMatchMessage>(OnClientMatchMessage);
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
internal void OnClientDisconnect()
|
||||
{
|
||||
InitializeData();
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
internal void OnStopClient()
|
||||
{
|
||||
ResetCanvas();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Server Match Message Handlers
|
||||
|
||||
[ServerCallback]
|
||||
void OnServerMatchMessage(NetworkConnectionToClient conn, ServerMatchMessage msg)
|
||||
{
|
||||
switch (msg.serverMatchOperation)
|
||||
{
|
||||
case ServerMatchOperation.None:
|
||||
{
|
||||
Debug.LogWarning("Missing ServerMatchOperation");
|
||||
break;
|
||||
}
|
||||
case ServerMatchOperation.Create:
|
||||
{
|
||||
OnServerCreateMatch(conn);
|
||||
break;
|
||||
}
|
||||
case ServerMatchOperation.Cancel:
|
||||
{
|
||||
OnServerCancelMatch(conn);
|
||||
break;
|
||||
}
|
||||
case ServerMatchOperation.Join:
|
||||
{
|
||||
OnServerJoinMatch(conn, msg.matchId);
|
||||
break;
|
||||
}
|
||||
case ServerMatchOperation.Leave:
|
||||
{
|
||||
OnServerLeaveMatch(conn, msg.matchId);
|
||||
break;
|
||||
}
|
||||
case ServerMatchOperation.Ready:
|
||||
{
|
||||
OnServerPlayerReady(conn, msg.matchId);
|
||||
break;
|
||||
}
|
||||
case ServerMatchOperation.Start:
|
||||
{
|
||||
OnServerStartMatch(conn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ServerCallback]
|
||||
void OnServerCreateMatch(NetworkConnectionToClient conn)
|
||||
{
|
||||
if (playerMatches.ContainsKey(conn)) return;
|
||||
|
||||
Guid newMatchId = Guid.NewGuid();
|
||||
matchConnections.Add(newMatchId, new HashSet<NetworkConnectionToClient>());
|
||||
matchConnections[newMatchId].Add(conn);
|
||||
playerMatches.Add(conn, newMatchId);
|
||||
openMatches.Add(newMatchId, new MatchInfo { matchId = newMatchId, maxPlayers = 2, players = 1 });
|
||||
|
||||
PlayerInfo playerInfo = playerInfos[conn];
|
||||
playerInfo.ready = false;
|
||||
playerInfo.matchId = newMatchId;
|
||||
playerInfos[conn] = playerInfo;
|
||||
|
||||
PlayerInfo[] infos = matchConnections[newMatchId].Select(playerConn => playerInfos[playerConn]).ToArray();
|
||||
|
||||
conn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Created, matchId = newMatchId, playerInfos = infos });
|
||||
|
||||
SendMatchList();
|
||||
}
|
||||
|
||||
[ServerCallback]
|
||||
void OnServerCancelMatch(NetworkConnectionToClient conn)
|
||||
{
|
||||
if (!playerMatches.ContainsKey(conn)) return;
|
||||
|
||||
conn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Cancelled });
|
||||
|
||||
Guid matchId;
|
||||
if (playerMatches.TryGetValue(conn, out matchId))
|
||||
{
|
||||
playerMatches.Remove(conn);
|
||||
openMatches.Remove(matchId);
|
||||
|
||||
foreach (NetworkConnectionToClient playerConn in matchConnections[matchId])
|
||||
{
|
||||
PlayerInfo playerInfo = playerInfos[playerConn];
|
||||
playerInfo.ready = false;
|
||||
playerInfo.matchId = Guid.Empty;
|
||||
playerInfos[playerConn] = playerInfo;
|
||||
playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Departed });
|
||||
}
|
||||
|
||||
SendMatchList();
|
||||
}
|
||||
}
|
||||
|
||||
[ServerCallback]
|
||||
void OnServerJoinMatch(NetworkConnectionToClient conn, Guid matchId)
|
||||
{
|
||||
if (!matchConnections.ContainsKey(matchId) || !openMatches.ContainsKey(matchId)) return;
|
||||
|
||||
MatchInfo matchInfo = openMatches[matchId];
|
||||
matchInfo.players++;
|
||||
openMatches[matchId] = matchInfo;
|
||||
matchConnections[matchId].Add(conn);
|
||||
|
||||
PlayerInfo playerInfo = playerInfos[conn];
|
||||
playerInfo.ready = false;
|
||||
playerInfo.matchId = matchId;
|
||||
playerInfos[conn] = playerInfo;
|
||||
|
||||
PlayerInfo[] infos = matchConnections[matchId].Select(playerConn => playerInfos[playerConn]).ToArray();
|
||||
SendMatchList();
|
||||
|
||||
conn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Joined, matchId = matchId, playerInfos = infos });
|
||||
|
||||
foreach (NetworkConnectionToClient playerConn in matchConnections[matchId])
|
||||
playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.UpdateRoom, playerInfos = infos });
|
||||
}
|
||||
|
||||
[ServerCallback]
|
||||
void OnServerLeaveMatch(NetworkConnectionToClient conn, Guid matchId)
|
||||
{
|
||||
MatchInfo matchInfo = openMatches[matchId];
|
||||
matchInfo.players--;
|
||||
openMatches[matchId] = matchInfo;
|
||||
|
||||
PlayerInfo playerInfo = playerInfos[conn];
|
||||
playerInfo.ready = false;
|
||||
playerInfo.matchId = Guid.Empty;
|
||||
playerInfos[conn] = playerInfo;
|
||||
|
||||
foreach (KeyValuePair<Guid, HashSet<NetworkConnectionToClient>> kvp in matchConnections)
|
||||
kvp.Value.Remove(conn);
|
||||
|
||||
HashSet<NetworkConnectionToClient> connections = matchConnections[matchId];
|
||||
PlayerInfo[] infos = connections.Select(playerConn => playerInfos[playerConn]).ToArray();
|
||||
|
||||
foreach (NetworkConnectionToClient playerConn in matchConnections[matchId])
|
||||
playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.UpdateRoom, playerInfos = infos });
|
||||
|
||||
SendMatchList();
|
||||
|
||||
conn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Departed });
|
||||
}
|
||||
|
||||
[ServerCallback]
|
||||
void OnServerPlayerReady(NetworkConnectionToClient conn, Guid matchId)
|
||||
{
|
||||
PlayerInfo playerInfo = playerInfos[conn];
|
||||
playerInfo.ready = !playerInfo.ready;
|
||||
playerInfos[conn] = playerInfo;
|
||||
|
||||
HashSet<NetworkConnectionToClient> connections = matchConnections[matchId];
|
||||
PlayerInfo[] infos = connections.Select(playerConn => playerInfos[playerConn]).ToArray();
|
||||
|
||||
foreach (NetworkConnectionToClient playerConn in matchConnections[matchId])
|
||||
playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.UpdateRoom, playerInfos = infos });
|
||||
}
|
||||
|
||||
[ServerCallback]
|
||||
void OnServerStartMatch(NetworkConnectionToClient conn)
|
||||
{
|
||||
if (!playerMatches.ContainsKey(conn)) return;
|
||||
|
||||
Guid matchId;
|
||||
if (playerMatches.TryGetValue(conn, out matchId))
|
||||
{
|
||||
GameObject matchControllerObject = Instantiate(matchControllerPrefab);
|
||||
matchControllerObject.GetComponent<NetworkMatch>().matchId = matchId;
|
||||
NetworkServer.Spawn(matchControllerObject);
|
||||
|
||||
MatchController matchController = matchControllerObject.GetComponent<MatchController>();
|
||||
|
||||
foreach (NetworkConnectionToClient playerConn in matchConnections[matchId])
|
||||
{
|
||||
playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Started });
|
||||
|
||||
GameObject player = Instantiate(NetworkManager.singleton.playerPrefab);
|
||||
player.GetComponent<NetworkMatch>().matchId = matchId;
|
||||
NetworkServer.AddPlayerForConnection(playerConn, player);
|
||||
|
||||
if (matchController.player1 == null)
|
||||
matchController.player1 = playerConn.identity;
|
||||
else
|
||||
matchController.player2 = playerConn.identity;
|
||||
|
||||
/* Reset ready state for after the match. */
|
||||
PlayerInfo playerInfo = playerInfos[playerConn];
|
||||
playerInfo.ready = false;
|
||||
playerInfos[playerConn] = playerInfo;
|
||||
}
|
||||
|
||||
matchController.startingPlayer = matchController.player1;
|
||||
matchController.currentPlayer = matchController.player1;
|
||||
|
||||
playerMatches.Remove(conn);
|
||||
openMatches.Remove(matchId);
|
||||
matchConnections.Remove(matchId);
|
||||
SendMatchList();
|
||||
|
||||
OnPlayerDisconnect += matchController.OnPlayerDisconnect;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends updated match list to all waiting connections or just one if specified
|
||||
/// </summary>
|
||||
/// <param name="conn"></param>
|
||||
[ServerCallback]
|
||||
internal void SendMatchList(NetworkConnectionToClient conn = null)
|
||||
{
|
||||
if (conn != null)
|
||||
conn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.List, matchInfos = openMatches.Values.ToArray() });
|
||||
else
|
||||
foreach (NetworkConnectionToClient waiter in waitingConnections)
|
||||
waiter.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.List, matchInfos = openMatches.Values.ToArray() });
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Client Match Message Handler
|
||||
|
||||
[ClientCallback]
|
||||
void OnClientMatchMessage(ClientMatchMessage msg)
|
||||
{
|
||||
switch (msg.clientMatchOperation)
|
||||
{
|
||||
case ClientMatchOperation.None:
|
||||
{
|
||||
Debug.LogWarning("Missing ClientMatchOperation");
|
||||
break;
|
||||
}
|
||||
case ClientMatchOperation.List:
|
||||
{
|
||||
openMatches.Clear();
|
||||
foreach (MatchInfo matchInfo in msg.matchInfos)
|
||||
openMatches.Add(matchInfo.matchId, matchInfo);
|
||||
|
||||
RefreshMatchList();
|
||||
break;
|
||||
}
|
||||
case ClientMatchOperation.Created:
|
||||
{
|
||||
localPlayerMatch = msg.matchId;
|
||||
ShowRoomView();
|
||||
roomGUI.RefreshRoomPlayers(msg.playerInfos);
|
||||
roomGUI.SetOwner(true);
|
||||
break;
|
||||
}
|
||||
case ClientMatchOperation.Cancelled:
|
||||
{
|
||||
localPlayerMatch = Guid.Empty;
|
||||
ShowLobbyView();
|
||||
break;
|
||||
}
|
||||
case ClientMatchOperation.Joined:
|
||||
{
|
||||
localJoinedMatch = msg.matchId;
|
||||
ShowRoomView();
|
||||
roomGUI.RefreshRoomPlayers(msg.playerInfos);
|
||||
roomGUI.SetOwner(false);
|
||||
break;
|
||||
}
|
||||
case ClientMatchOperation.Departed:
|
||||
{
|
||||
localJoinedMatch = Guid.Empty;
|
||||
ShowLobbyView();
|
||||
break;
|
||||
}
|
||||
case ClientMatchOperation.UpdateRoom:
|
||||
{
|
||||
roomGUI.RefreshRoomPlayers(msg.playerInfos);
|
||||
break;
|
||||
}
|
||||
case ClientMatchOperation.Started:
|
||||
{
|
||||
lobbyView.SetActive(false);
|
||||
roomView.SetActive(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
void ShowLobbyView()
|
||||
{
|
||||
lobbyView.SetActive(true);
|
||||
roomView.SetActive(false);
|
||||
|
||||
foreach (Transform child in matchList.transform)
|
||||
if (child.gameObject.GetComponent<MatchGUI>().GetMatchId() == selectedMatch)
|
||||
{
|
||||
Toggle toggle = child.gameObject.GetComponent<Toggle>();
|
||||
toggle.isOn = true;
|
||||
}
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
void ShowRoomView()
|
||||
{
|
||||
lobbyView.SetActive(false);
|
||||
roomView.SetActive(true);
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
void RefreshMatchList()
|
||||
{
|
||||
foreach (Transform child in matchList.transform)
|
||||
Destroy(child.gameObject);
|
||||
|
||||
joinButton.interactable = false;
|
||||
|
||||
foreach (MatchInfo matchInfo in openMatches.Values)
|
||||
{
|
||||
GameObject newMatch = Instantiate(matchPrefab, Vector3.zero, Quaternion.identity);
|
||||
newMatch.transform.SetParent(matchList.transform, false);
|
||||
newMatch.GetComponent<MatchGUI>().SetMatchInfo(matchInfo);
|
||||
|
||||
Toggle toggle = newMatch.GetComponent<Toggle>();
|
||||
toggle.group = toggleGroup;
|
||||
if (matchInfo.matchId == selectedMatch)
|
||||
toggle.isOn = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c12d7cb6cdb799041927819f22a2c931
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Scripts/CanvasController.cs
|
||||
uploadId: 736421
|
47
Assets/Mirror/Examples/MultipleMatches/Scripts/CellGUI.cs
Normal file
47
Assets/Mirror/Examples/MultipleMatches/Scripts/CellGUI.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Mirror.Examples.MultipleMatch
|
||||
{
|
||||
public class CellGUI : MonoBehaviour
|
||||
{
|
||||
public MatchController matchController;
|
||||
public CellValue cellValue;
|
||||
|
||||
[Header("GUI References")]
|
||||
public Image image;
|
||||
public Button button;
|
||||
|
||||
[Header("Diagnostics")]
|
||||
[ReadOnly, SerializeField] internal NetworkIdentity playerIdentity;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
matchController.MatchCells.Add(cellValue, this);
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
public void MakePlay()
|
||||
{
|
||||
if (matchController.currentPlayer.isLocalPlayer)
|
||||
matchController.CmdMakePlay(cellValue);
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
public void SetPlayer(NetworkIdentity playerIdentity)
|
||||
{
|
||||
if (playerIdentity != null)
|
||||
{
|
||||
this.playerIdentity = playerIdentity;
|
||||
image.color = this.playerIdentity.isLocalPlayer ? Color.blue : Color.red;
|
||||
button.interactable = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.playerIdentity = null;
|
||||
image.color = Color.white;
|
||||
button.interactable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cda2a394a443474689a3c6d6044f7b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Scripts/CellGUI.cs
|
||||
uploadId: 736421
|
@ -0,0 +1,312 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Mirror.Examples.MultipleMatch
|
||||
{
|
||||
[RequireComponent(typeof(NetworkMatch))]
|
||||
public class MatchController : NetworkBehaviour
|
||||
{
|
||||
internal readonly SyncDictionary<NetworkIdentity, MatchPlayerData> matchPlayerData = new SyncDictionary<NetworkIdentity, MatchPlayerData>();
|
||||
internal readonly Dictionary<CellValue, CellGUI> MatchCells = new Dictionary<CellValue, CellGUI>();
|
||||
|
||||
CellValue boardScore = CellValue.None;
|
||||
bool playAgain = false;
|
||||
|
||||
[Header("GUI References")]
|
||||
public CanvasGroup canvasGroup;
|
||||
public Text gameText;
|
||||
public Button exitButton;
|
||||
public Button playAgainButton;
|
||||
public Text winCountLocal;
|
||||
public Text winCountOpponent;
|
||||
|
||||
[Header("Diagnostics")]
|
||||
[ReadOnly, SerializeField] internal CanvasController canvasController;
|
||||
[ReadOnly, SerializeField] internal NetworkIdentity player1;
|
||||
[ReadOnly, SerializeField] internal NetworkIdentity player2;
|
||||
[ReadOnly, SerializeField] internal NetworkIdentity startingPlayer;
|
||||
|
||||
[SyncVar(hook = nameof(UpdateGameUI))]
|
||||
[ReadOnly, SerializeField] internal NetworkIdentity currentPlayer;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
#if UNITY_2022_2_OR_NEWER
|
||||
canvasController = GameObject.FindAnyObjectByType<CanvasController>();
|
||||
#else
|
||||
// Deprecated in Unity 2023.1
|
||||
canvasController = GameObject.FindObjectOfType<CanvasController>();
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void OnStartServer()
|
||||
{
|
||||
StartCoroutine(AddPlayersToMatchController());
|
||||
}
|
||||
|
||||
// For the SyncDictionary to properly fire the update callback, we must
|
||||
// wait a frame before adding the players to the already spawned MatchController
|
||||
IEnumerator AddPlayersToMatchController()
|
||||
{
|
||||
yield return null;
|
||||
|
||||
matchPlayerData.Add(player1, new MatchPlayerData { playerIndex = CanvasController.playerInfos[player1.connectionToClient].playerIndex });
|
||||
matchPlayerData.Add(player2, new MatchPlayerData { playerIndex = CanvasController.playerInfos[player2.connectionToClient].playerIndex });
|
||||
}
|
||||
|
||||
public override void OnStartClient()
|
||||
{
|
||||
canvasGroup.alpha = 1f;
|
||||
canvasGroup.interactable = true;
|
||||
canvasGroup.blocksRaycasts = true;
|
||||
|
||||
exitButton.gameObject.SetActive(false);
|
||||
playAgainButton.gameObject.SetActive(false);
|
||||
|
||||
// Assign handler for SyncDictionary changes
|
||||
matchPlayerData.OnChange = UpdateWins;
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
public void UpdateGameUI(NetworkIdentity _, NetworkIdentity newPlayerTurn)
|
||||
{
|
||||
if (!newPlayerTurn) return;
|
||||
|
||||
if (newPlayerTurn.gameObject.GetComponent<NetworkIdentity>().isLocalPlayer)
|
||||
{
|
||||
gameText.text = "Your Turn";
|
||||
gameText.color = Color.blue;
|
||||
}
|
||||
else
|
||||
{
|
||||
gameText.text = "Their Turn";
|
||||
gameText.color = Color.red;
|
||||
}
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
public void UpdateWins(SyncDictionary<NetworkIdentity, MatchPlayerData>.Operation op, NetworkIdentity key, MatchPlayerData matchPlayerData)
|
||||
{
|
||||
if (key.gameObject.GetComponent<NetworkIdentity>().isLocalPlayer)
|
||||
winCountLocal.text = $"Player {matchPlayerData.playerIndex}\n{matchPlayerData.wins}";
|
||||
else
|
||||
winCountOpponent.text = $"Player {matchPlayerData.playerIndex}\n{matchPlayerData.wins}";
|
||||
}
|
||||
|
||||
[Command(requiresAuthority = false)]
|
||||
public void CmdMakePlay(CellValue cellValue, NetworkConnectionToClient sender = null)
|
||||
{
|
||||
// If wrong player or cell already taken, ignore
|
||||
if (sender.identity != currentPlayer || MatchCells[cellValue].playerIdentity != null)
|
||||
return;
|
||||
|
||||
MatchCells[cellValue].playerIdentity = currentPlayer;
|
||||
RpcUpdateCell(cellValue, currentPlayer);
|
||||
|
||||
MatchPlayerData mpd = matchPlayerData[currentPlayer];
|
||||
mpd.currentScore = mpd.currentScore | cellValue;
|
||||
matchPlayerData[currentPlayer] = mpd;
|
||||
|
||||
boardScore |= cellValue;
|
||||
|
||||
if (CheckWinner(mpd.currentScore))
|
||||
{
|
||||
mpd.wins += 1;
|
||||
matchPlayerData[currentPlayer] = mpd;
|
||||
RpcShowWinner(currentPlayer);
|
||||
currentPlayer = null;
|
||||
}
|
||||
else if (boardScore == CellValue.Full)
|
||||
{
|
||||
RpcShowWinner(null);
|
||||
currentPlayer = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set currentPlayer SyncVar so clients know whose turn it is
|
||||
currentPlayer = currentPlayer == player1 ? player2 : player1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[ServerCallback]
|
||||
bool CheckWinner(CellValue currentScore)
|
||||
{
|
||||
if ((currentScore & CellValue.TopRow) == CellValue.TopRow)
|
||||
return true;
|
||||
if ((currentScore & CellValue.MidRow) == CellValue.MidRow)
|
||||
return true;
|
||||
if ((currentScore & CellValue.BotRow) == CellValue.BotRow)
|
||||
return true;
|
||||
if ((currentScore & CellValue.LeftCol) == CellValue.LeftCol)
|
||||
return true;
|
||||
if ((currentScore & CellValue.MidCol) == CellValue.MidCol)
|
||||
return true;
|
||||
if ((currentScore & CellValue.RightCol) == CellValue.RightCol)
|
||||
return true;
|
||||
if ((currentScore & CellValue.Diag1) == CellValue.Diag1)
|
||||
return true;
|
||||
if ((currentScore & CellValue.Diag2) == CellValue.Diag2)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void RpcUpdateCell(CellValue cellValue, NetworkIdentity player)
|
||||
{
|
||||
MatchCells[cellValue].SetPlayer(player);
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void RpcShowWinner(NetworkIdentity winner)
|
||||
{
|
||||
foreach (CellGUI cellGUI in MatchCells.Values)
|
||||
cellGUI.GetComponent<Button>().interactable = false;
|
||||
|
||||
if (winner == null)
|
||||
{
|
||||
gameText.text = "Draw!";
|
||||
gameText.color = Color.yellow;
|
||||
}
|
||||
else if (winner.gameObject.GetComponent<NetworkIdentity>().isLocalPlayer)
|
||||
{
|
||||
gameText.text = "Winner!";
|
||||
gameText.color = Color.blue;
|
||||
}
|
||||
else
|
||||
{
|
||||
gameText.text = "Loser!";
|
||||
gameText.color = Color.red;
|
||||
}
|
||||
|
||||
exitButton.gameObject.SetActive(true);
|
||||
playAgainButton.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
// Assigned in inspector to ReplayButton::OnClick
|
||||
[ClientCallback]
|
||||
public void RequestPlayAgain()
|
||||
{
|
||||
playAgainButton.gameObject.SetActive(false);
|
||||
CmdPlayAgain();
|
||||
}
|
||||
|
||||
[Command(requiresAuthority = false)]
|
||||
public void CmdPlayAgain(NetworkConnectionToClient sender = null)
|
||||
{
|
||||
if (!playAgain)
|
||||
playAgain = true;
|
||||
else
|
||||
{
|
||||
playAgain = false;
|
||||
RestartGame();
|
||||
}
|
||||
}
|
||||
|
||||
[ServerCallback]
|
||||
public void RestartGame()
|
||||
{
|
||||
boardScore = CellValue.None;
|
||||
|
||||
NetworkIdentity[] keys = new NetworkIdentity[matchPlayerData.Keys.Count];
|
||||
matchPlayerData.Keys.CopyTo(keys, 0);
|
||||
|
||||
foreach (NetworkIdentity identity in keys)
|
||||
{
|
||||
MatchPlayerData mpd = matchPlayerData[identity];
|
||||
mpd.currentScore = CellValue.None;
|
||||
matchPlayerData[identity] = mpd;
|
||||
}
|
||||
|
||||
RpcRestartGame();
|
||||
|
||||
startingPlayer = startingPlayer == player1 ? player2 : player1;
|
||||
currentPlayer = startingPlayer;
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void RpcRestartGame()
|
||||
{
|
||||
foreach (CellGUI cellGUI in MatchCells.Values)
|
||||
cellGUI.SetPlayer(null);
|
||||
|
||||
exitButton.gameObject.SetActive(false);
|
||||
playAgainButton.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
// Assigned in inspector to BackButton::OnClick
|
||||
[Client]
|
||||
public void RequestExitGame()
|
||||
{
|
||||
exitButton.gameObject.SetActive(false);
|
||||
playAgainButton.gameObject.SetActive(false);
|
||||
CmdRequestExitGame();
|
||||
}
|
||||
|
||||
[Command(requiresAuthority = false)]
|
||||
public void CmdRequestExitGame(NetworkConnectionToClient sender = null)
|
||||
{
|
||||
StartCoroutine(ServerEndMatch(sender, false));
|
||||
}
|
||||
|
||||
[ServerCallback]
|
||||
public void OnPlayerDisconnect(NetworkConnectionToClient conn)
|
||||
{
|
||||
// Check that the disconnecting client is a player in this match
|
||||
if (player1 == conn.identity || player2 == conn.identity)
|
||||
StartCoroutine(ServerEndMatch(conn, true));
|
||||
}
|
||||
|
||||
[ServerCallback]
|
||||
public IEnumerator ServerEndMatch(NetworkConnectionToClient conn, bool disconnected)
|
||||
{
|
||||
RpcExitGame();
|
||||
|
||||
canvasController.OnPlayerDisconnect -= OnPlayerDisconnect;
|
||||
|
||||
// Wait for the ClientRpc to get out ahead of object destruction
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
|
||||
// Mirror will clean up the disconnecting client so we only need to clean up the other remaining client.
|
||||
// If both players are just returning to the Lobby, we need to remove both connection Players
|
||||
|
||||
if (!disconnected)
|
||||
{
|
||||
NetworkServer.RemovePlayerForConnection(player1.connectionToClient, RemovePlayerOptions.Destroy);
|
||||
CanvasController.waitingConnections.Add(player1.connectionToClient);
|
||||
|
||||
NetworkServer.RemovePlayerForConnection(player2.connectionToClient, RemovePlayerOptions.Destroy);
|
||||
CanvasController.waitingConnections.Add(player2.connectionToClient);
|
||||
}
|
||||
else if (conn == player1.connectionToClient)
|
||||
{
|
||||
// player1 has disconnected - send player2 back to Lobby
|
||||
NetworkServer.RemovePlayerForConnection(player2.connectionToClient, RemovePlayerOptions.Destroy);
|
||||
CanvasController.waitingConnections.Add(player2.connectionToClient);
|
||||
}
|
||||
else if (conn == player2.connectionToClient)
|
||||
{
|
||||
// player2 has disconnected - send player1 back to Lobby
|
||||
NetworkServer.RemovePlayerForConnection(player1.connectionToClient, RemovePlayerOptions.Destroy);
|
||||
CanvasController.waitingConnections.Add(player1.connectionToClient);
|
||||
}
|
||||
|
||||
// Skip a frame to allow the Removal(s) to complete
|
||||
yield return null;
|
||||
|
||||
// Send latest match list
|
||||
canvasController.SendMatchList();
|
||||
|
||||
NetworkServer.Destroy(gameObject);
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void RpcExitGame()
|
||||
{
|
||||
canvasController.OnMatchEnded();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ccb1dd1fc7cc624e9bff1d0d7a5c741
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Scripts/MatchController.cs
|
||||
uploadId: 736421
|
48
Assets/Mirror/Examples/MultipleMatches/Scripts/MatchGUI.cs
Normal file
48
Assets/Mirror/Examples/MultipleMatches/Scripts/MatchGUI.cs
Normal file
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Mirror.Examples.MultipleMatch
|
||||
{
|
||||
public class MatchGUI : MonoBehaviour
|
||||
{
|
||||
Guid matchId;
|
||||
|
||||
[Header("GUI Elements")]
|
||||
public Image image;
|
||||
public Toggle toggleButton;
|
||||
public Text matchName;
|
||||
public Text playerCount;
|
||||
|
||||
[Header("Diagnostics")]
|
||||
[ReadOnly, SerializeField] internal CanvasController canvasController;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
#if UNITY_2022_2_OR_NEWER
|
||||
canvasController = GameObject.FindAnyObjectByType<CanvasController>();
|
||||
#else
|
||||
// Deprecated in Unity 2023.1
|
||||
canvasController = GameObject.FindObjectOfType<CanvasController>();
|
||||
#endif
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
public void OnToggleClicked(bool isOn)
|
||||
{
|
||||
canvasController.SelectMatch(isOn ? matchId : Guid.Empty);
|
||||
image.color = isOn ? new Color(0f, 1f, 0f, 0.5f) : new Color(1f, 1f, 1f, 0.2f);
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
public Guid GetMatchId() => matchId;
|
||||
|
||||
[ClientCallback]
|
||||
public void SetMatchInfo(MatchInfo infos)
|
||||
{
|
||||
matchId = infos.matchId;
|
||||
matchName.text = $"Match {infos.matchId.ToString().Substring(0, 8)}";
|
||||
playerCount.text = $"{infos.players} / {infos.maxPlayers}";
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e875a237ce12c3145b20f17222f10b68
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Scripts/MatchGUI.cs
|
||||
uploadId: 736421
|
117
Assets/Mirror/Examples/MultipleMatches/Scripts/MatchMessages.cs
Normal file
117
Assets/Mirror/Examples/MultipleMatches/Scripts/MatchMessages.cs
Normal file
@ -0,0 +1,117 @@
|
||||
using System;
|
||||
|
||||
namespace Mirror.Examples.MultipleMatch
|
||||
{
|
||||
/// <summary>
|
||||
/// Match message to be sent to the server
|
||||
/// </summary>
|
||||
public struct ServerMatchMessage : NetworkMessage
|
||||
{
|
||||
public ServerMatchOperation serverMatchOperation;
|
||||
public Guid matchId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Match message to be sent to the client
|
||||
/// </summary>
|
||||
public struct ClientMatchMessage : NetworkMessage
|
||||
{
|
||||
public ClientMatchOperation clientMatchOperation;
|
||||
public Guid matchId;
|
||||
public MatchInfo[] matchInfos;
|
||||
public PlayerInfo[] playerInfos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Information about a match
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public struct MatchInfo
|
||||
{
|
||||
public Guid matchId;
|
||||
public byte players;
|
||||
public byte maxPlayers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Information about a player
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public struct PlayerInfo
|
||||
{
|
||||
public int playerIndex;
|
||||
public bool ready;
|
||||
public Guid matchId;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct MatchPlayerData
|
||||
{
|
||||
public int playerIndex;
|
||||
public int wins;
|
||||
public CellValue currentScore;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Match operation to execute on the server
|
||||
/// </summary>
|
||||
public enum ServerMatchOperation : byte
|
||||
{
|
||||
None,
|
||||
Create,
|
||||
Cancel,
|
||||
Start,
|
||||
Join,
|
||||
Leave,
|
||||
Ready
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Match operation to execute on the client
|
||||
/// </summary>
|
||||
public enum ClientMatchOperation : byte
|
||||
{
|
||||
None,
|
||||
List,
|
||||
Created,
|
||||
Cancelled,
|
||||
Joined,
|
||||
Departed,
|
||||
UpdateRoom,
|
||||
Started
|
||||
}
|
||||
|
||||
// A1 | B1 | C1
|
||||
// ---+----+---
|
||||
// A2 | B2 | C2
|
||||
// ---+----+---
|
||||
// A3 | B3 | C3
|
||||
|
||||
[Flags]
|
||||
public enum CellValue : ushort
|
||||
{
|
||||
None,
|
||||
A1 = 1 << 0,
|
||||
B1 = 1 << 1,
|
||||
C1 = 1 << 2,
|
||||
A2 = 1 << 3,
|
||||
B2 = 1 << 4,
|
||||
C2 = 1 << 5,
|
||||
A3 = 1 << 6,
|
||||
B3 = 1 << 7,
|
||||
C3 = 1 << 8,
|
||||
|
||||
// winning combinations
|
||||
TopRow = A1 + B1 + C1,
|
||||
MidRow = A2 + B2 + C2,
|
||||
BotRow = A3 + B3 + C3,
|
||||
LeftCol = A1 + A2 + A3,
|
||||
MidCol = B1 + B2 + B3,
|
||||
RightCol = C1 + C2 + C3,
|
||||
Diag1 = A1 + B2 + C3,
|
||||
Diag2 = A3 + B2 + C1,
|
||||
|
||||
// board is full (winner / draw)
|
||||
Full = TopRow + MidRow + BotRow
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a98b377d8481e52449b996e45a015b8c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Scripts/MatchMessages.cs
|
||||
uploadId: 736421
|
@ -0,0 +1,110 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mirror.Examples.MultipleMatch
|
||||
{
|
||||
[AddComponentMenu("")]
|
||||
public class MatchNetworkManager : NetworkManager
|
||||
{
|
||||
[Header("Match GUI")]
|
||||
public GameObject canvas;
|
||||
public CanvasController canvasController;
|
||||
|
||||
/// <summary>
|
||||
/// Runs on both Server and Client
|
||||
/// Networking is NOT initialized when this fires
|
||||
/// </summary>
|
||||
public override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
canvasController.InitializeData();
|
||||
}
|
||||
|
||||
#region Server System Callbacks
|
||||
|
||||
/// <summary>
|
||||
/// Called on the server when a client is ready.
|
||||
/// <para>The default implementation of this function calls NetworkServer.SetClientReady() to continue the network setup process.</para>
|
||||
/// </summary>
|
||||
/// <param name="conn">Connection from client.</param>
|
||||
public override void OnServerReady(NetworkConnectionToClient conn)
|
||||
{
|
||||
base.OnServerReady(conn);
|
||||
canvasController.OnServerReady(conn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called on the server when a client disconnects.
|
||||
/// <para>This is called on the Server when a Client disconnects from the Server. Use an override to decide what should happen when a disconnection is detected.</para>
|
||||
/// </summary>
|
||||
/// <param name="conn">Connection from client.</param>
|
||||
public override void OnServerDisconnect(NetworkConnectionToClient conn)
|
||||
{
|
||||
StartCoroutine(DoServerDisconnect(conn));
|
||||
}
|
||||
|
||||
IEnumerator DoServerDisconnect(NetworkConnectionToClient conn)
|
||||
{
|
||||
yield return canvasController.OnServerDisconnect(conn);
|
||||
base.OnServerDisconnect(conn);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Client System Callbacks
|
||||
|
||||
/// <summary>
|
||||
/// Called on clients when disconnected from a server.
|
||||
/// <para>This is called on the client when it disconnects from the server. Override this function to decide what happens when the client disconnects.</para>
|
||||
/// </summary>
|
||||
public override void OnClientDisconnect()
|
||||
{
|
||||
canvasController.OnClientDisconnect();
|
||||
base.OnClientDisconnect();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Start & Stop Callbacks
|
||||
|
||||
/// <summary>
|
||||
/// This is invoked when a server is started - including when a host is started.
|
||||
/// <para>StartServer has multiple signatures, but they all cause this hook to be called.</para>
|
||||
/// </summary>
|
||||
public override void OnStartServer()
|
||||
{
|
||||
if (mode == NetworkManagerMode.ServerOnly)
|
||||
canvas.SetActive(true);
|
||||
|
||||
canvasController.OnStartServer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is invoked when the client is started.
|
||||
/// </summary>
|
||||
public override void OnStartClient()
|
||||
{
|
||||
canvas.SetActive(true);
|
||||
canvasController.OnStartClient();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called when a server is stopped - including when a host is stopped.
|
||||
/// </summary>
|
||||
public override void OnStopServer()
|
||||
{
|
||||
canvasController.OnStopServer();
|
||||
canvas.SetActive(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called when a client is stopped.
|
||||
/// </summary>
|
||||
public override void OnStopClient()
|
||||
{
|
||||
canvasController.OnStopClient();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b15c78bb8ab8da42a94aa0bc3081814
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Scripts/MatchNetworkManager.cs
|
||||
uploadId: 736421
|
17
Assets/Mirror/Examples/MultipleMatches/Scripts/PlayerGUI.cs
Normal file
17
Assets/Mirror/Examples/MultipleMatches/Scripts/PlayerGUI.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Mirror.Examples.MultipleMatch
|
||||
{
|
||||
public class PlayerGUI : MonoBehaviour
|
||||
{
|
||||
public Text playerName;
|
||||
|
||||
[ClientCallback]
|
||||
public void SetPlayerInfo(PlayerInfo info)
|
||||
{
|
||||
playerName.text = $"Player {info.playerIndex}";
|
||||
playerName.color = info.ready ? Color.green : Color.red;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f61e9bc3715eb904b91222a5526f63d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Scripts/PlayerGUI.cs
|
||||
uploadId: 736421
|
45
Assets/Mirror/Examples/MultipleMatches/Scripts/RoomGUI.cs
Normal file
45
Assets/Mirror/Examples/MultipleMatches/Scripts/RoomGUI.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Mirror.Examples.MultipleMatch
|
||||
{
|
||||
public class RoomGUI : MonoBehaviour
|
||||
{
|
||||
public GameObject playerList;
|
||||
public GameObject playerPrefab;
|
||||
public GameObject cancelButton;
|
||||
public GameObject leaveButton;
|
||||
public Button startButton;
|
||||
public bool owner;
|
||||
|
||||
[ClientCallback]
|
||||
public void RefreshRoomPlayers(PlayerInfo[] playerInfos)
|
||||
{
|
||||
foreach (Transform child in playerList.transform)
|
||||
Destroy(child.gameObject);
|
||||
|
||||
startButton.interactable = false;
|
||||
bool everyoneReady = true;
|
||||
|
||||
foreach (PlayerInfo playerInfo in playerInfos)
|
||||
{
|
||||
GameObject newPlayer = Instantiate(playerPrefab, Vector3.zero, Quaternion.identity);
|
||||
newPlayer.transform.SetParent(playerList.transform, false);
|
||||
newPlayer.GetComponent<PlayerGUI>().SetPlayerInfo(playerInfo);
|
||||
|
||||
if (!playerInfo.ready)
|
||||
everyoneReady = false;
|
||||
}
|
||||
|
||||
startButton.interactable = everyoneReady && owner && (playerInfos.Length > 1);
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
public void SetOwner(bool owner)
|
||||
{
|
||||
this.owner = owner;
|
||||
cancelButton.SetActive(owner);
|
||||
leaveButton.SetActive(!owner);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc0f113afba9a074b9a3e4fb56f16abb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 129321
|
||||
packageName: Mirror
|
||||
packageVersion: 96.0.1
|
||||
assetPath: Assets/Mirror/Examples/MultipleMatches/Scripts/RoomGUI.cs
|
||||
uploadId: 736421
|
Reference in New Issue
Block a user