Basic Networking done
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:
|
||||
144
Assets/Mirror/Examples/MultipleMatches/Prefabs/CellGUI.prefab
Normal file
144
Assets/Mirror/Examples/MultipleMatches/Prefabs/CellGUI.prefab
Normal file
@@ -0,0 +1,144 @@
|
||||
%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: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 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
|
||||
--- !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: 1392445389, guid: f70555f144d8491a825f0804e09c671c, 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_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_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
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,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ab8c221183f0094eb04b7f6eb569e7b
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e101d385946c91b4c81f318efc723a88
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
293
Assets/Mirror/Examples/MultipleMatches/Prefabs/MatchGUI.prefab
Normal file
293
Assets/Mirror/Examples/MultipleMatches/Prefabs/MatchGUI.prefab
Normal file
@@ -0,0 +1,293 @@
|
||||
%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: 708705254, guid: f70555f144d8491a825f0804e09c671c, 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_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: -765806418, guid: f70555f144d8491a825f0804e09c671c, 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_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
|
||||
--- !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: 2109663825, guid: f70555f144d8491a825f0804e09c671c, 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_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_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
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_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: 708705254, guid: f70555f144d8491a825f0804e09c671c, 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_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,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df3727c2222378b4ca786485a8b09981
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,80 @@
|
||||
%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}
|
||||
- component: {fileID: -3043620344775994659}
|
||||
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_ConstrainProportionsScale: 0
|
||||
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
|
||||
serverOnly: 0
|
||||
visible: 0
|
||||
m_AssetId: 11d2414f1e120a14c98cba6866e5348f
|
||||
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:
|
||||
--- !u!114 &-3043620344775994659
|
||||
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: 1020a74962faada4b807ac5dc053a4cf, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
syncMode: 0
|
||||
syncInterval: 0.1
|
||||
currentMatchDebug:
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11d2414f1e120a14c98cba6866e5348f
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
182
Assets/Mirror/Examples/MultipleMatches/Prefabs/PlayerGUI.prefab
Normal file
182
Assets/Mirror/Examples/MultipleMatches/Prefabs/PlayerGUI.prefab
Normal file
@@ -0,0 +1,182 @@
|
||||
%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: -765806418, guid: f70555f144d8491a825f0804e09c671c, 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_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
|
||||
--- !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: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 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: -900027084, guid: f70555f144d8491a825f0804e09c671c, 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,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 504f86497324bc040be44f6f88b6cc73
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
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.
|
||||
7
Assets/Mirror/Examples/MultipleMatches/README.md.meta
Normal file
7
Assets/Mirror/Examples/MultipleMatches/README.md.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9749e23e4e90e0646afc81061710a927
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
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:
|
||||
2889
Assets/Mirror/Examples/MultipleMatches/Scenes/Main.unity
Normal file
2889
Assets/Mirror/Examples/MultipleMatches/Scenes/Main.unity
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa1f875396fa7d348a782cebc2f75d7c
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
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,671 @@
|
||||
using System;
|
||||
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<NetworkConnection> OnPlayerDisconnected;
|
||||
|
||||
/// <summary>
|
||||
/// Cross-reference of client that created the corresponding match in openMatches below
|
||||
/// </summary>
|
||||
internal static readonly Dictionary<NetworkConnection, Guid> playerMatches = new Dictionary<NetworkConnection, 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<NetworkConnection>> matchConnections = new Dictionary<Guid, HashSet<NetworkConnection>>();
|
||||
|
||||
/// <summary>
|
||||
/// Player informations by Network Connection
|
||||
/// </summary>
|
||||
internal static readonly Dictionary<NetworkConnection, PlayerInfo> playerInfos = new Dictionary<NetworkConnection, PlayerInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// Network Connections that have neither started nor joined a match yet
|
||||
/// </summary>
|
||||
internal static readonly List<NetworkConnection> waitingConnections = new List<NetworkConnection>();
|
||||
|
||||
/// <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;
|
||||
|
||||
#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>
|
||||
public void SelectMatch(Guid matchId)
|
||||
{
|
||||
if (!NetworkClient.active) return;
|
||||
|
||||
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>
|
||||
public void RequestCreateMatch()
|
||||
{
|
||||
if (!NetworkClient.active) return;
|
||||
|
||||
NetworkClient.connection.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Create });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigned in inspector to Join button
|
||||
/// </summary>
|
||||
public void RequestJoinMatch()
|
||||
{
|
||||
if (!NetworkClient.active || selectedMatch == Guid.Empty) return;
|
||||
|
||||
NetworkClient.connection.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Join, matchId = selectedMatch });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigned in inspector to Leave button
|
||||
/// </summary>
|
||||
public void RequestLeaveMatch()
|
||||
{
|
||||
if (!NetworkClient.active || localJoinedMatch == Guid.Empty) return;
|
||||
|
||||
NetworkClient.connection.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Leave, matchId = localJoinedMatch });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigned in inspector to Cancel button
|
||||
/// </summary>
|
||||
public void RequestCancelMatch()
|
||||
{
|
||||
if (!NetworkClient.active || localPlayerMatch == Guid.Empty) return;
|
||||
|
||||
NetworkClient.connection.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Cancel });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigned in inspector to Ready button
|
||||
/// </summary>
|
||||
public void RequestReadyChange()
|
||||
{
|
||||
if (!NetworkClient.active || (localPlayerMatch == Guid.Empty && localJoinedMatch == Guid.Empty)) return;
|
||||
|
||||
Guid matchId = localPlayerMatch == Guid.Empty ? localJoinedMatch : localPlayerMatch;
|
||||
|
||||
NetworkClient.connection.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Ready, matchId = matchId });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigned in inspector to Start button
|
||||
/// </summary>
|
||||
public void RequestStartMatch()
|
||||
{
|
||||
if (!NetworkClient.active || localPlayerMatch == Guid.Empty) return;
|
||||
|
||||
NetworkClient.connection.Send(new ServerMatchMessage { serverMatchOperation = ServerMatchOperation.Start });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called from <see cref="MatchController.RpcExitGame"/>
|
||||
/// </summary>
|
||||
public void OnMatchEnded()
|
||||
{
|
||||
if (!NetworkClient.active) return;
|
||||
|
||||
localPlayerMatch = Guid.Empty;
|
||||
localJoinedMatch = Guid.Empty;
|
||||
ShowLobbyView();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends updated match list to all waiting connections or just one if specified
|
||||
/// </summary>
|
||||
/// <param name="conn"></param>
|
||||
internal void SendMatchList(NetworkConnection conn = null)
|
||||
{
|
||||
if (!NetworkServer.active) return;
|
||||
|
||||
if (conn != null)
|
||||
{
|
||||
conn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.List, matchInfos = openMatches.Values.ToArray() });
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var waiter in waitingConnections)
|
||||
{
|
||||
waiter.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.List, matchInfos = openMatches.Values.ToArray() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Server & Client Callbacks
|
||||
|
||||
// Methods in this section are called from MatchNetworkManager's corresponding methods
|
||||
|
||||
internal void OnStartServer()
|
||||
{
|
||||
if (!NetworkServer.active) return;
|
||||
|
||||
InitializeData();
|
||||
NetworkServer.RegisterHandler<ServerMatchMessage>(OnServerMatchMessage);
|
||||
}
|
||||
|
||||
internal void OnServerReady(NetworkConnection conn)
|
||||
{
|
||||
if (!NetworkServer.active) return;
|
||||
|
||||
waitingConnections.Add(conn);
|
||||
playerInfos.Add(conn, new PlayerInfo { playerIndex = this.playerIndex, ready = false });
|
||||
playerIndex++;
|
||||
|
||||
SendMatchList();
|
||||
}
|
||||
|
||||
internal void OnServerDisconnect(NetworkConnection conn)
|
||||
{
|
||||
if (!NetworkServer.active) return;
|
||||
|
||||
// Invoke OnPlayerDisconnected on all instances of MatchController
|
||||
OnPlayerDisconnected?.Invoke(conn);
|
||||
|
||||
Guid matchId;
|
||||
if (playerMatches.TryGetValue(conn, out matchId))
|
||||
{
|
||||
playerMatches.Remove(conn);
|
||||
openMatches.Remove(matchId);
|
||||
|
||||
foreach (NetworkConnection 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<NetworkConnection>> kvp in matchConnections)
|
||||
{
|
||||
kvp.Value.Remove(conn);
|
||||
}
|
||||
|
||||
PlayerInfo playerInfo = playerInfos[conn];
|
||||
if (playerInfo.matchId != Guid.Empty)
|
||||
{
|
||||
MatchInfo matchInfo;
|
||||
if (openMatches.TryGetValue(playerInfo.matchId, out matchInfo))
|
||||
{
|
||||
matchInfo.players--;
|
||||
openMatches[playerInfo.matchId] = matchInfo;
|
||||
}
|
||||
|
||||
HashSet<NetworkConnection> connections;
|
||||
if (matchConnections.TryGetValue(playerInfo.matchId, out connections))
|
||||
{
|
||||
PlayerInfo[] infos = connections.Select(playerConn => playerInfos[playerConn]).ToArray();
|
||||
|
||||
foreach (NetworkConnection playerConn in matchConnections[playerInfo.matchId])
|
||||
{
|
||||
if (playerConn != conn)
|
||||
{
|
||||
playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.UpdateRoom, playerInfos = infos });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SendMatchList();
|
||||
}
|
||||
|
||||
internal void OnStopServer()
|
||||
{
|
||||
ResetCanvas();
|
||||
}
|
||||
|
||||
internal void OnClientConnect(NetworkConnection conn)
|
||||
{
|
||||
playerInfos.Add(conn, new PlayerInfo { playerIndex = this.playerIndex, ready = false });
|
||||
}
|
||||
|
||||
internal void OnStartClient()
|
||||
{
|
||||
if (!NetworkClient.active) return;
|
||||
|
||||
InitializeData();
|
||||
ShowLobbyView();
|
||||
createButton.gameObject.SetActive(true);
|
||||
joinButton.gameObject.SetActive(true);
|
||||
NetworkClient.RegisterHandler<ClientMatchMessage>(OnClientMatchMessage);
|
||||
}
|
||||
|
||||
internal void OnClientDisconnect()
|
||||
{
|
||||
if (!NetworkClient.active) return;
|
||||
|
||||
InitializeData();
|
||||
}
|
||||
|
||||
internal void OnStopClient()
|
||||
{
|
||||
ResetCanvas();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Server Match Message Handlers
|
||||
|
||||
void OnServerMatchMessage(NetworkConnection conn, ServerMatchMessage msg)
|
||||
{
|
||||
if (!NetworkServer.active) return;
|
||||
|
||||
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.Start:
|
||||
{
|
||||
OnServerStartMatch(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnServerPlayerReady(NetworkConnection conn, Guid matchId)
|
||||
{
|
||||
if (!NetworkServer.active) return;
|
||||
|
||||
PlayerInfo playerInfo = playerInfos[conn];
|
||||
playerInfo.ready = !playerInfo.ready;
|
||||
playerInfos[conn] = playerInfo;
|
||||
|
||||
HashSet<NetworkConnection> connections = matchConnections[matchId];
|
||||
PlayerInfo[] infos = connections.Select(playerConn => playerInfos[playerConn]).ToArray();
|
||||
|
||||
foreach (NetworkConnection playerConn in matchConnections[matchId])
|
||||
{
|
||||
playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.UpdateRoom, playerInfos = infos });
|
||||
}
|
||||
}
|
||||
|
||||
void OnServerLeaveMatch(NetworkConnection conn, Guid matchId)
|
||||
{
|
||||
if (!NetworkServer.active) return;
|
||||
|
||||
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<NetworkConnection>> kvp in matchConnections)
|
||||
{
|
||||
kvp.Value.Remove(conn);
|
||||
}
|
||||
|
||||
HashSet<NetworkConnection> connections = matchConnections[matchId];
|
||||
PlayerInfo[] infos = connections.Select(playerConn => playerInfos[playerConn]).ToArray();
|
||||
|
||||
foreach (NetworkConnection playerConn in matchConnections[matchId])
|
||||
{
|
||||
playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.UpdateRoom, playerInfos = infos });
|
||||
}
|
||||
|
||||
SendMatchList();
|
||||
|
||||
conn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Departed });
|
||||
}
|
||||
|
||||
void OnServerCreateMatch(NetworkConnection conn)
|
||||
{
|
||||
if (!NetworkServer.active || playerMatches.ContainsKey(conn)) return;
|
||||
|
||||
Guid newMatchId = Guid.NewGuid();
|
||||
matchConnections.Add(newMatchId, new HashSet<NetworkConnection>());
|
||||
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();
|
||||
}
|
||||
|
||||
void OnServerCancelMatch(NetworkConnection conn)
|
||||
{
|
||||
if (!NetworkServer.active || !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 (NetworkConnection 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();
|
||||
}
|
||||
}
|
||||
|
||||
void OnServerStartMatch(NetworkConnection conn)
|
||||
{
|
||||
if (!NetworkServer.active || !playerMatches.ContainsKey(conn)) return;
|
||||
|
||||
Guid matchId;
|
||||
if (playerMatches.TryGetValue(conn, out matchId))
|
||||
{
|
||||
GameObject matchControllerObject = Instantiate(matchControllerPrefab);
|
||||
#pragma warning disable 618
|
||||
matchControllerObject.GetComponent<NetworkMatch>().matchId = matchId;
|
||||
#pragma warning restore 618
|
||||
NetworkServer.Spawn(matchControllerObject);
|
||||
|
||||
MatchController matchController = matchControllerObject.GetComponent<MatchController>();
|
||||
|
||||
foreach (NetworkConnection playerConn in matchConnections[matchId])
|
||||
{
|
||||
playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.Started });
|
||||
|
||||
GameObject player = Instantiate(NetworkManager.singleton.playerPrefab);
|
||||
#pragma warning disable 618
|
||||
player.GetComponent<NetworkMatch>().matchId = matchId;
|
||||
#pragma warning restore 618
|
||||
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();
|
||||
|
||||
OnPlayerDisconnected += matchController.OnPlayerDisconnected;
|
||||
}
|
||||
}
|
||||
|
||||
void OnServerJoinMatch(NetworkConnection conn, Guid matchId)
|
||||
{
|
||||
if (!NetworkServer.active || !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 (NetworkConnection playerConn in matchConnections[matchId])
|
||||
{
|
||||
playerConn.Send(new ClientMatchMessage { clientMatchOperation = ClientMatchOperation.UpdateRoom, playerInfos = infos });
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Client Match Message Handler
|
||||
|
||||
void OnClientMatchMessage(ClientMatchMessage msg)
|
||||
{
|
||||
if (!NetworkClient.active) return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
//toggle.onValueChanged.Invoke(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShowRoomView()
|
||||
{
|
||||
lobbyView.SetActive(false);
|
||||
roomView.SetActive(true);
|
||||
}
|
||||
|
||||
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);
|
||||
newMatch.GetComponent<Toggle>().group = toggleGroup;
|
||||
if (matchInfo.matchId == selectedMatch)
|
||||
{
|
||||
newMatch.GetComponent<Toggle>().isOn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c12d7cb6cdb799041927819f22a2c931
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
46
Assets/Mirror/Examples/MultipleMatches/Scripts/CellGUI.cs
Normal file
46
Assets/Mirror/Examples/MultipleMatches/Scripts/CellGUI.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
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 - Do Not Modify")]
|
||||
public NetworkIdentity playerIdentity;
|
||||
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
matchController.MatchCells.Add(cellValue, this);
|
||||
}
|
||||
|
||||
public void MakePlay()
|
||||
{
|
||||
if (matchController.currentPlayer.isLocalPlayer)
|
||||
matchController.CmdMakePlay(cellValue);
|
||||
}
|
||||
|
||||
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,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cda2a394a443474689a3c6d6044f7b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,315 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Mirror.Examples.MultipleMatch
|
||||
{
|
||||
#pragma warning disable 618
|
||||
[RequireComponent(typeof(NetworkMatchChecker))]
|
||||
#pragma warning restore 618
|
||||
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 - Do Not Modify")]
|
||||
public CanvasController canvasController;
|
||||
public NetworkIdentity player1;
|
||||
public NetworkIdentity player2;
|
||||
public NetworkIdentity startingPlayer;
|
||||
|
||||
[SyncVar(hook = nameof(UpdateGameUI))]
|
||||
public NetworkIdentity currentPlayer;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
canvasController = FindObjectOfType<CanvasController>();
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
matchPlayerData.Callback += UpdateWins;
|
||||
|
||||
canvasGroup.alpha = 1f;
|
||||
canvasGroup.interactable = true;
|
||||
canvasGroup.blocksRaycasts = true;
|
||||
|
||||
exitButton.gameObject.SetActive(false);
|
||||
playAgainButton.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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 = 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
[Client]
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
[Server]
|
||||
public void RestartGame()
|
||||
{
|
||||
foreach (CellGUI cellGUI in MatchCells.Values)
|
||||
cellGUI.SetPlayer(null);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
public void OnPlayerDisconnected(NetworkConnection conn)
|
||||
{
|
||||
// Check that the disconnecting client is a player in this match
|
||||
if (player1 == conn.identity || player2 == conn.identity)
|
||||
{
|
||||
StartCoroutine(ServerEndMatch(conn, true));
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator ServerEndMatch(NetworkConnection conn, bool disconnected)
|
||||
{
|
||||
canvasController.OnPlayerDisconnected -= OnPlayerDisconnected;
|
||||
|
||||
RpcExitGame();
|
||||
|
||||
// Skip a frame so the message goes out ahead of object destruction
|
||||
yield return null;
|
||||
|
||||
// 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, true);
|
||||
CanvasController.waitingConnections.Add(player1.connectionToClient);
|
||||
|
||||
NetworkServer.RemovePlayerForConnection(player2.connectionToClient, true);
|
||||
CanvasController.waitingConnections.Add(player2.connectionToClient);
|
||||
}
|
||||
else if (conn == player1.connectionToClient)
|
||||
{
|
||||
// player1 has disconnected - send player2 back to Lobby
|
||||
NetworkServer.RemovePlayerForConnection(player2.connectionToClient, true);
|
||||
CanvasController.waitingConnections.Add(player2.connectionToClient);
|
||||
}
|
||||
else if (conn == player2.connectionToClient)
|
||||
{
|
||||
// player2 has disconnected - send player1 back to Lobby
|
||||
NetworkServer.RemovePlayerForConnection(player1.connectionToClient, true);
|
||||
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,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ccb1dd1fc7cc624e9bff1d0d7a5c741
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
44
Assets/Mirror/Examples/MultipleMatches/Scripts/MatchGUI.cs
Normal file
44
Assets/Mirror/Examples/MultipleMatches/Scripts/MatchGUI.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
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 - Do Not Modify")]
|
||||
public CanvasController canvasController;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
canvasController = FindObjectOfType<CanvasController>();
|
||||
toggleButton.onValueChanged.AddListener(delegate { OnToggleClicked(); });
|
||||
}
|
||||
|
||||
public void OnToggleClicked()
|
||||
{
|
||||
canvasController.SelectMatch(toggleButton.isOn ? matchId : Guid.Empty);
|
||||
image.color = toggleButton.isOn ? new Color(0f, 1f, 0f, 0.5f) : new Color(1f, 1f, 1f, 0.2f);
|
||||
}
|
||||
|
||||
public Guid GetMatchId()
|
||||
{
|
||||
return matchId;
|
||||
}
|
||||
|
||||
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,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e875a237ce12c3145b20f17222f10b68
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
118
Assets/Mirror/Examples/MultipleMatches/Scripts/MatchMessages.cs
Normal file
118
Assets/Mirror/Examples/MultipleMatches/Scripts/MatchMessages.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
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,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a98b377d8481e52449b996e45a015b8c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,125 @@
|
||||
using UnityEngine;
|
||||
|
||||
/*
|
||||
Documentation: https://mirror-networking.gitbook.io/docs/components/network-manager
|
||||
API Reference: https://mirror-networking.com/docs/api/Mirror.NetworkManager.html
|
||||
*/
|
||||
|
||||
namespace Mirror.Examples.MultipleMatch
|
||||
{
|
||||
[AddComponentMenu("")]
|
||||
public class MatchNetworkManager : NetworkManager
|
||||
{
|
||||
[Header("Match GUI")]
|
||||
public GameObject canvas;
|
||||
public CanvasController canvasController;
|
||||
|
||||
#region Unity Callbacks
|
||||
|
||||
/// <summary>
|
||||
/// Runs on both Server and Client
|
||||
/// Networking is NOT initialized when this fires
|
||||
/// </summary>
|
||||
public override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
canvasController.InitializeData();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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(NetworkConnection 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(NetworkConnection conn)
|
||||
{
|
||||
canvasController.OnServerDisconnect(conn);
|
||||
base.OnServerDisconnect(conn);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Client System Callbacks
|
||||
|
||||
/// <summary>
|
||||
/// Called on the client when connected to a server.
|
||||
/// <para>The default implementation of this function sets the client as ready and adds a player. Override the function to dictate what happens when the client connects.</para>
|
||||
/// </summary>
|
||||
/// <param name="conn">Connection to the server.</param>
|
||||
public override void OnClientConnect(NetworkConnection conn)
|
||||
{
|
||||
base.OnClientConnect(conn);
|
||||
canvasController.OnClientConnect(conn);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <param name="conn">Connection to the server.</param>
|
||||
public override void OnClientDisconnect(NetworkConnection conn)
|
||||
{
|
||||
canvasController.OnClientDisconnect();
|
||||
base.OnClientDisconnect(conn);
|
||||
}
|
||||
|
||||
#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,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b15c78bb8ab8da42a94aa0bc3081814
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
16
Assets/Mirror/Examples/MultipleMatches/Scripts/PlayerGUI.cs
Normal file
16
Assets/Mirror/Examples/MultipleMatches/Scripts/PlayerGUI.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Mirror.Examples.MultipleMatch
|
||||
{
|
||||
public class PlayerGUI : MonoBehaviour
|
||||
{
|
||||
public Text playerName;
|
||||
|
||||
public void SetPlayerInfo(PlayerInfo info)
|
||||
{
|
||||
playerName.text = "Player " + info.playerIndex;
|
||||
playerName.color = info.ready ? Color.green : Color.red;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f61e9bc3715eb904b91222a5526f63d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
48
Assets/Mirror/Examples/MultipleMatches/Scripts/RoomGUI.cs
Normal file
48
Assets/Mirror/Examples/MultipleMatches/Scripts/RoomGUI.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
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;
|
||||
|
||||
public void RefreshRoomPlayers(PlayerInfo[] playerInfos)
|
||||
{
|
||||
// Debug.Log($"RefreshRoomPlayers: {playerInfos.Length} 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);
|
||||
}
|
||||
|
||||
public void SetOwner(bool owner)
|
||||
{
|
||||
this.owner = owner;
|
||||
cancelButton.SetActive(owner);
|
||||
leaveButton.SetActive(!owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc0f113afba9a074b9a3e4fb56f16abb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user