lvjincheng 4 ani în urmă
părinte
comite
9fc164b3fd
24 a modificat fișierele cu 1456 adăugiri și 325 ștergeri
  1. 233 2
      Assets/BowArrow/Resources/Prefabs/Views/PKGameSettleView.prefab
  2. 5 3
      Assets/BowArrow/Resources/Prefabs/Views/PKGameView.prefab
  3. 82 147
      Assets/BowArrow/Scripts/Game/ArmBow.cs
  4. 12 1
      Assets/BowArrow/Scripts/Game/Arrow.cs
  5. 62 24
      Assets/BowArrow/Scripts/Game/ArrowCamera.cs
  6. 5 5
      Assets/BowArrow/Scripts/Game/BowCamera.cs
  7. 11 1
      Assets/BowArrow/Scripts/GlobalData.cs
  8. 8 0
      Assets/BowArrow/Scripts/Manager/GameMode/OnlineObject.meta
  9. 5 0
      Assets/BowArrow/Scripts/Manager/GameMode/OnlineObject/ArmBowSyncData.cs
  10. 11 0
      Assets/BowArrow/Scripts/Manager/GameMode/OnlineObject/ArmBowSyncData.cs.meta
  11. 83 0
      Assets/BowArrow/Scripts/Manager/GameMode/OnlineObject/ArrowSync.cs
  12. 11 0
      Assets/BowArrow/Scripts/Manager/GameMode/OnlineObject/ArrowSync.cs.meta
  13. 345 3
      Assets/BowArrow/Scripts/Manager/GameMode/PKGameMode_OnlinePK.cs
  14. 2 0
      Assets/BowArrow/Scripts/Manager/LoginMgr.cs
  15. 48 59
      Assets/BowArrow/Scripts/Network/SocketPlayer.cs
  16. 1 0
      Assets/BowArrow/Scripts/View/PKGameOptionView.cs
  17. 71 15
      Assets/BowArrow/Scripts/View/PKGameReadyView.cs
  18. 25 8
      Assets/BowArrow/Scripts/View/PKGameSettleView.cs
  19. 65 5
      Assets/BowArrow/Scripts/View/PKGameView.cs
  20. 8 1
      Assets/BowArrow/Scripts/View/PKMatchView.cs
  21. 43 2
      Assets/BowArrow/Scripts/View/PKMatchingView.cs
  22. 257 0
      Assets/DependAsset/JC/JCEngine.cs
  23. 11 0
      Assets/DependAsset/JC/JCEngine.cs.meta
  24. 52 49
      Assets/DependAsset/JC/JCSocketIO.cs

+ 233 - 2
Assets/BowArrow/Resources/Prefabs/Views/PKGameSettleView.prefab

@@ -189,6 +189,8 @@ MonoBehaviour:
   m_EditorClassIdentifier: 
   m_EditorClassIdentifier: 
   textID: 105
   textID: 105
   layoutRebuildObject: {fileID: 0}
   layoutRebuildObject: {fileID: 0}
+  textFormatArgs: []
+  languageFontSizes: []
 --- !u!1 &3360787652013184894
 --- !u!1 &3360787652013184894
 GameObject:
 GameObject:
   m_ObjectHideFlags: 0
   m_ObjectHideFlags: 0
@@ -283,6 +285,8 @@ MonoBehaviour:
   m_EditorClassIdentifier: 
   m_EditorClassIdentifier: 
   textID: 90
   textID: 90
   layoutRebuildObject: {fileID: 0}
   layoutRebuildObject: {fileID: 0}
+  textFormatArgs: []
+  languageFontSizes: []
 --- !u!1 &4000660164863388918
 --- !u!1 &4000660164863388918
 GameObject:
 GameObject:
   m_ObjectHideFlags: 0
   m_ObjectHideFlags: 0
@@ -377,6 +381,8 @@ MonoBehaviour:
   m_EditorClassIdentifier: 
   m_EditorClassIdentifier: 
   textID: 91
   textID: 91
   layoutRebuildObject: {fileID: 0}
   layoutRebuildObject: {fileID: 0}
+  textFormatArgs: []
+  languageFontSizes: []
 --- !u!1 &4234390746813627421
 --- !u!1 &4234390746813627421
 GameObject:
 GameObject:
   m_ObjectHideFlags: 0
   m_ObjectHideFlags: 0
@@ -414,7 +420,7 @@ RectTransform:
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_AnchorMin: {x: 0, y: 0}
   m_AnchorMin: {x: 0, y: 0}
   m_AnchorMax: {x: 0, y: 0}
   m_AnchorMax: {x: 0, y: 0}
-  m_AnchoredPosition: {x: 36, y: 0}
+  m_AnchoredPosition: {x: 34.2428, y: 0}
   m_SizeDelta: {x: 0, y: 0}
   m_SizeDelta: {x: 0, y: 0}
   m_Pivot: {x: 0.5, y: 0.5}
   m_Pivot: {x: 0.5, y: 0.5}
 --- !u!222 &4192900400895089148
 --- !u!222 &4192900400895089148
@@ -502,6 +508,141 @@ MonoBehaviour:
   m_EditorClassIdentifier: 
   m_EditorClassIdentifier: 
   textID: 102
   textID: 102
   layoutRebuildObject: {fileID: 5704473190286268411}
   layoutRebuildObject: {fileID: 5704473190286268411}
+  textFormatArgs: []
+  languageFontSizes: []
+--- !u!1 &5008691783001009752
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 8018399360315740214}
+  - component: {fileID: 8401370157308201665}
+  - component: {fileID: 1972974744011693609}
+  - component: {fileID: 5093875714959467692}
+  m_Layer: 5
+  m_Name: BtnBack
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 0
+--- !u!224 &8018399360315740214
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5008691783001009752}
+  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: 3103744211167819680}
+  m_Father: {fileID: 6205683939515071217}
+  m_RootOrder: 3
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 1}
+  m_AnchorMax: {x: 0, y: 1}
+  m_AnchoredPosition: {x: 265, y: -28}
+  m_SizeDelta: {x: 151, y: 61}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &8401370157308201665
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5008691783001009752}
+  m_CullTransparentMesh: 0
+--- !u!114 &1972974744011693609
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5008691783001009752}
+  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_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 21300000, guid: 8ccd496b30ced39438603d237003eafe, type: 3}
+  m_Type: 1
+  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 &5093875714959467692
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5008691783001009752}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Navigation:
+    m_Mode: 3
+    m_WrapAround: 0
+    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: Selected
+    m_DisabledTrigger: Disabled
+  m_Interactable: 1
+  m_TargetGraphic: {fileID: 1972974744011693609}
+  m_OnClick:
+    m_PersistentCalls:
+      m_Calls:
+      - m_Target: {fileID: 8251348454529071114}
+        m_TargetAssemblyTypeName: PKGameSettleView, Assembly-CSharp
+        m_MethodName: GoHome
+        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!1 &5454067006710410434
 --- !u!1 &5454067006710410434
 GameObject:
 GameObject:
   m_ObjectHideFlags: 0
   m_ObjectHideFlags: 0
@@ -539,7 +680,7 @@ RectTransform:
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_AnchorMin: {x: 0, y: 0}
   m_AnchorMin: {x: 0, y: 0}
   m_AnchorMax: {x: 0, y: 0}
   m_AnchorMax: {x: 0, y: 0}
-  m_AnchoredPosition: {x: 116, y: 0}
+  m_AnchoredPosition: {x: 111.73967, y: 0}
   m_SizeDelta: {x: 0, y: 0}
   m_SizeDelta: {x: 0, y: 0}
   m_Pivot: {x: 0.5, y: 0.5}
   m_Pivot: {x: 0.5, y: 0.5}
 --- !u!222 &1871444126788684677
 --- !u!222 &1871444126788684677
@@ -627,6 +768,8 @@ MonoBehaviour:
   m_EditorClassIdentifier: 
   m_EditorClassIdentifier: 
   textID: 104
   textID: 104
   layoutRebuildObject: {fileID: 5704473190286268411}
   layoutRebuildObject: {fileID: 5704473190286268411}
+  textFormatArgs: []
+  languageFontSizes: []
 --- !u!1 &6168405928774381856
 --- !u!1 &6168405928774381856
 GameObject:
 GameObject:
   m_ObjectHideFlags: 0
   m_ObjectHideFlags: 0
@@ -721,6 +864,8 @@ MonoBehaviour:
   m_EditorClassIdentifier: 
   m_EditorClassIdentifier: 
   textID: 89
   textID: 89
   layoutRebuildObject: {fileID: 0}
   layoutRebuildObject: {fileID: 0}
+  textFormatArgs: []
+  languageFontSizes: []
 --- !u!1 &6205683937731073832
 --- !u!1 &6205683937731073832
 GameObject:
 GameObject:
   m_ObjectHideFlags: 0
   m_ObjectHideFlags: 0
@@ -907,6 +1052,8 @@ MonoBehaviour:
   m_EditorClassIdentifier: 
   m_EditorClassIdentifier: 
   textID: 106
   textID: 106
   layoutRebuildObject: {fileID: 0}
   layoutRebuildObject: {fileID: 0}
+  textFormatArgs: []
+  languageFontSizes: []
 --- !u!1 &6205683938153467025
 --- !u!1 &6205683938153467025
 GameObject:
 GameObject:
   m_ObjectHideFlags: 0
   m_ObjectHideFlags: 0
@@ -1017,6 +1164,8 @@ MonoBehaviour:
   m_EditorClassIdentifier: 
   m_EditorClassIdentifier: 
   textID: 106
   textID: 106
   layoutRebuildObject: {fileID: 0}
   layoutRebuildObject: {fileID: 0}
+  textFormatArgs: []
+  languageFontSizes: []
 --- !u!1 &6205683938434936820
 --- !u!1 &6205683938434936820
 GameObject:
 GameObject:
   m_ObjectHideFlags: 0
   m_ObjectHideFlags: 0
@@ -2309,6 +2458,7 @@ RectTransform:
   - {fileID: 6205683939278506988}
   - {fileID: 6205683939278506988}
   - {fileID: 6205683938787035072}
   - {fileID: 6205683938787035072}
   - {fileID: 6205683938788414475}
   - {fileID: 6205683938788414475}
+  - {fileID: 8018399360315740214}
   m_Father: {fileID: 6205683939588628677}
   m_Father: {fileID: 6205683939588628677}
   m_RootOrder: 2
   m_RootOrder: 2
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@@ -2733,6 +2883,87 @@ MonoBehaviour:
   m_EditorClassIdentifier: 
   m_EditorClassIdentifier: 
   textID: 105
   textID: 105
   layoutRebuildObject: {fileID: 0}
   layoutRebuildObject: {fileID: 0}
+  textFormatArgs: []
+  languageFontSizes: []
+--- !u!1 &8648083681334419574
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 3103744211167819680}
+  - component: {fileID: 3844400631572140300}
+  - component: {fileID: 4413037686295861844}
+  m_Layer: 5
+  m_Name: Text
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &3103744211167819680
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 8648083681334419574}
+  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: 8018399360315740214}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &3844400631572140300
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 8648083681334419574}
+  m_CullTransparentMesh: 1
+--- !u!114 &4413037686295861844
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 8648083681334419574}
+  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: 0.7137255, g: 0.3529412, b: 0, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 12800000, guid: 1ad2cf6c2f09744489d8c60b3fe3bab2, type: 3}
+    m_FontSize: 26
+    m_FontStyle: 0
+    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: "\u8FD4\u56DE"
 --- !u!1 &8725788648309036209
 --- !u!1 &8725788648309036209
 GameObject:
 GameObject:
   m_ObjectHideFlags: 0
   m_ObjectHideFlags: 0

+ 5 - 3
Assets/BowArrow/Resources/Prefabs/Views/PKGameView.prefab

@@ -282,6 +282,7 @@ MonoBehaviour:
   textID: 93
   textID: 93
   layoutRebuildObject: {fileID: 0}
   layoutRebuildObject: {fileID: 0}
   textFormatArgs: []
   textFormatArgs: []
+  languageFontSizes: []
 --- !u!1 &2120877169636818123
 --- !u!1 &2120877169636818123
 GameObject:
 GameObject:
   m_ObjectHideFlags: 0
   m_ObjectHideFlags: 0
@@ -400,7 +401,7 @@ RectTransform:
   m_AnchorMin: {x: 0.5, y: 1}
   m_AnchorMin: {x: 0.5, y: 1}
   m_AnchorMax: {x: 0.5, y: 1}
   m_AnchorMax: {x: 0.5, y: 1}
   m_AnchoredPosition: {x: 0, y: -17.5}
   m_AnchoredPosition: {x: 0, y: -17.5}
-  m_SizeDelta: {x: 200, y: 26.666666}
+  m_SizeDelta: {x: 200, y: 40}
   m_Pivot: {x: 0.5, y: 0.5}
   m_Pivot: {x: 0.5, y: 0.5}
 --- !u!222 &2120877169851161211
 --- !u!222 &2120877169851161211
 CanvasRenderer:
 CanvasRenderer:
@@ -459,6 +460,7 @@ MonoBehaviour:
   textID: 92
   textID: 92
   layoutRebuildObject: {fileID: 0}
   layoutRebuildObject: {fileID: 0}
   textFormatArgs: []
   textFormatArgs: []
+  languageFontSizes: []
 --- !u!1 &2120877169957024407
 --- !u!1 &2120877169957024407
 GameObject:
 GameObject:
   m_ObjectHideFlags: 0
   m_ObjectHideFlags: 0
@@ -753,7 +755,7 @@ RectTransform:
   m_AnchorMin: {x: 0.5, y: 0.5}
   m_AnchorMin: {x: 0.5, y: 0.5}
   m_AnchorMax: {x: 0.5, y: 0.5}
   m_AnchorMax: {x: 0.5, y: 0.5}
   m_AnchoredPosition: {x: 0, y: -16}
   m_AnchoredPosition: {x: 0, y: -16}
-  m_SizeDelta: {x: 120, y: 32}
+  m_SizeDelta: {x: 120, y: 40}
   m_Pivot: {x: 0.5, y: 0.5}
   m_Pivot: {x: 0.5, y: 0.5}
 --- !u!222 &2120877170295618110
 --- !u!222 &2120877170295618110
 CanvasRenderer:
 CanvasRenderer:
@@ -1643,7 +1645,7 @@ RectTransform:
   m_AnchorMin: {x: 0.5, y: 0.5}
   m_AnchorMin: {x: 0.5, y: 0.5}
   m_AnchorMax: {x: 0.5, y: 0.5}
   m_AnchorMax: {x: 0.5, y: 0.5}
   m_AnchoredPosition: {x: 0, y: 0}
   m_AnchoredPosition: {x: 0, y: 0}
-  m_SizeDelta: {x: 200, y: 26.666666}
+  m_SizeDelta: {x: 200, y: 40}
   m_Pivot: {x: 0.5, y: 0.5}
   m_Pivot: {x: 0.5, y: 0.5}
 --- !u!222 &2120877171554691201
 --- !u!222 &2120877171554691201
 CanvasRenderer:
 CanvasRenderer:

+ 82 - 147
Assets/BowArrow/Scripts/Game/ArmBow.cs

@@ -7,7 +7,7 @@ public class ArmBow : MonoBehaviour
 {
 {
     [SerializeField] AnimationPlayer AP_arm;
     [SerializeField] AnimationPlayer AP_arm;
     [SerializeField] AnimationPlayer AP_bow;
     [SerializeField] AnimationPlayer AP_bow;
-    [SerializeField] GameObject arrow;
+    [SerializeField] public GameObject arrow;
     BowCamera _bowCamera;
     BowCamera _bowCamera;
     BowCamera bowCamera {
     BowCamera bowCamera {
         get {
         get {
@@ -22,26 +22,77 @@ public class ArmBow : MonoBehaviour
     [NonSerialized] public int shootBackTime = 0;
     [NonSerialized] public int shootBackTime = 0;
     [NonSerialized] public float shootOffsetAngleScale = 0;
     [NonSerialized] public float shootOffsetAngleScale = 0;
 
 
-    bool canShoot = false;
-    bool pulling = false;
-    bool readying = false;
-
     //禁止准备的外部接口
     //禁止准备的外部接口
     [NonSerialized] public bool banReady = false;
     [NonSerialized] public bool banReady = false;
     //禁止射击的外部接口
     //禁止射击的外部接口
     [NonSerialized] public bool banShoot = false;
     [NonSerialized] public bool banShoot = false;
-    //禁止被用户输入控制
-    [NonSerialized] public bool banUserShoot = false;
-
-    //九轴姿态记录
-    // [NonSerialized] public Quaternion[] recordRotations = new Quaternion[100];
-    // float[] recordRotationVars = new float[99];
-    // [NonSerialized] public int recordCount = 0;
+    //禁止逻辑,只用于同步状态和渲染,目前用于联机
+    [NonSerialized] public bool banLogic = false;
 
 
     //过去几帧的镜头值记录
     //过去几帧的镜头值记录
     Quaternion[] cameraRotations = new Quaternion[6];
     Quaternion[] cameraRotations = new Quaternion[6];
     int cameraRotationHasRecordCount = 0;
     int cameraRotationHasRecordCount = 0;
 
 
+    #region logic state 
+        [NonSerialized] public int phase = -1; //当前阶段
+        void UpdatePhase() {
+            if (phase == -1) return;
+            if (phase == 0) { //拉弓前的准备
+                if (arm_ani_index_cur != 0) {
+                    AP_arm.play(arm_ani_index_cur = 0, WrapMode.Once);
+                    AP_arm.completeCallback = onComplete;
+                } 
+                if (bow_ani_index_cur != 0) {
+                    AP_bow.play(bow_ani_index_cur = 0, WrapMode.Once);
+                } 
+            } else if (phase == 1) { //拉弓过程
+                if (arm_ani_index_cur != 2) {
+                    AP_arm.play(arm_ani_index_cur = 2, WrapMode.Once);
+                    AP_arm.completeCallback = onComplete;
+                } 
+                if (bow_ani_index_cur != 2) {
+                    AP_bow.play(bow_ani_index_cur = 2, WrapMode.Once);
+                } 
+                this.bowCamera.updateFollowPullBow();
+            } else if (phase == 2) { //拉完完成,等待发射
+                if (arm_ani_index_cur != 2) {
+                    AP_arm.play(arm_ani_index_cur = 2, WrapMode.Once);
+                    AP_arm.completeCallback = onComplete;
+                } 
+                if (bow_ani_index_cur != 2) {
+                    AP_bow.play(bow_ani_index_cur = 2, WrapMode.Once);
+                } 
+            } else if (phase == 3) { //射出后
+                if (arm_ani_index_cur != 0) {
+                    AP_arm.play(arm_ani_index_cur = 0, WrapMode.Once);
+                    AP_arm.completeCallback = onComplete;
+                } 
+                if (bow_ani_index_cur != 0) {
+                    AP_bow.play(bow_ani_index_cur = 0, WrapMode.Once);
+                } 
+            }
+            if (!IsCanShoot()) {
+                this.bowCamera.updateGiveUpPullBow();
+            }
+        }
+        void onComplete(AnimationPlayerCompleteResult res) {
+            if (res.index == 0 && !banLogic) {
+                this.phase = 1;
+            }
+            else if (res.index == 2 && !banLogic) {
+                this.phase = 2;
+                GameMgr.ins.gameMode.ResumeTimeCounting(this);
+            }
+        }
+        public bool IsCanShoot() {
+            return phase == 2;
+        }
+    #endregion
+    #region display state
+        int arm_ani_index_cur = -1;
+        int bow_ani_index_cur = -1;
+    #endregion 
+
     private static ArmBow _ins;
     private static ArmBow _ins;
     public static ArmBow ins {
     public static ArmBow ins {
         get {
         get {
@@ -59,6 +110,8 @@ public class ArmBow : MonoBehaviour
         int currentShootLevel = LoginMgr.myUserInfo.shootLevel;
         int currentShootLevel = LoginMgr.myUserInfo.shootLevel;
         shootBackTime = new int[]{0, 2, 5}[currentShootLevel];
         shootBackTime = new int[]{0, 2, 5}[currentShootLevel];
         shootOffsetAngleScale = new float[]{0, 10f, 10f}[currentShootLevel];
         shootOffsetAngleScale = new float[]{0, 10f, 10f}[currentShootLevel];
+
+        this.arrow.transform.Find("Head/_hunse_jian").gameObject.layer = LayerMask.NameToLayer("ArmBow");
     }
     }
 
 
     void Start()
     void Start()
@@ -66,12 +119,19 @@ public class ArmBow : MonoBehaviour
         this.readyShoot();
         this.readyShoot();
     }
     }
 
 
+    void OnEnable() 
+    {
+        AudioMgr.GetAudioSource(this.gameObject).clip = null;
+    }
+
+    void Update()
+    {
+        UpdatePhase();
+        if (Input.GetKeyDown(KeyCode.Q)) this.ADS_fire();
+    }
+
     void FixedUpdate()
     void FixedUpdate()
     {
     {
-        if (this.canShoot)
-        {
-            if (DebugBowPower.ins) DebugBowPower.ins.DoUpdate();
-        }
         // 记录一些旋转角---start
         // 记录一些旋转角---start
         if (this.bowCamera) {
         if (this.bowCamera) {
             for (int i = cameraRotations.Length - 1; i > 0 ; i--) {
             for (int i = cameraRotations.Length - 1; i > 0 ; i--) {
@@ -83,122 +143,25 @@ public class ArmBow : MonoBehaviour
         // 记录一些旋转角---end
         // 记录一些旋转角---end
     }
     }
 
 
-    void Update()
-    {
-        if (Input.GetKeyDown(KeyCode.Q)) 
-        {
-            this.ADS_fire();
-        }
-        if (this.pulling) {
-            this.bowCamera.updateFollowPullBow();
-        } 
-        else if (!this.canShoot)
-        {
-            this.bowCamera.updateGiveUpPullBow();
-        }
-    }
-
-    void onComplete(AnimationPlayerCompleteResult res) {
-        if (res.index == 0) {
-            this.readying = true;
-            this.idle();
-            this.Invoke("idleToADS", 0.1f);
-        }
-        else if (res.index == 2) {
-            this.ADS_idle();
-        }
-    }
-
-    public void ready() {
+    public void readyShoot() {
+        if (banLogic) return;
+        this.bowCamera.SetCameraFieldOfViewRecord(60);
         if (banReady) return;
         if (banReady) return;
         GameMgr.ins.gameMode.PauseTimeCounting(this);
         GameMgr.ins.gameMode.PauseTimeCounting(this);
         GameMgr.ins.gameMode.onBowReady();
         GameMgr.ins.gameMode.onBowReady();
         this.arrow.SetActive(true);
         this.arrow.SetActive(true);
-        AP_arm.play(0, WrapMode.Once);
-        AP_bow.play(0, WrapMode.Once);
-        AP_arm.completeCallback = onComplete;
-        this.pulling = false;
-        this.canShoot = false;
-    }
-
-    void idle() {
-        AP_arm.play(1, WrapMode.Loop);
-        AP_bow.play(1, WrapMode.Loop);
-        AP_arm.completeCallback = null;
-        this.pulling = false;
-        this.canShoot = false;
-        if (DebugBowPower.ins) DebugBowPower.ins.Init();
-    }
-
-    public void idleToADS() {
-        AP_arm.play(2, WrapMode.Once);
-        AP_bow.play(2, WrapMode.Once);
-        AP_arm.completeCallback = onComplete;
-        this.pulling = true;
-        this.canShoot = false;
-    }
-
-    void ADS_idle() {
-        GameMgr.ins.gameMode.ResumeTimeCounting(this);
-        this.canShoot = true;
-        this.pulling = false;
-        if (DebugBowPower.ins) DebugBowPower.ins.PullFinish();
+        this.phase = 0;
     }
     }
 
 
     public void ADS_fire() {
     public void ADS_fire() {
-        if (!canShoot || banShoot || GameMgr.ins.gamePause || banUserShoot) return;
+        if (!IsCanShoot() || banShoot || GameMgr.ins.gamePause || banLogic) return;
         GameMgr.ins.gameMode.onBowShoot();
         GameMgr.ins.gameMode.onBowShoot();
-        this.pulling = false;
-        this.canShoot = false;
-        this.readying = false;
-        AP_bow.play(0, WrapMode.Once);
+        this.phase = 3;
         this.arrow.SetActive(false);
         this.arrow.SetActive(false);
         shoot();
         shoot();
     }
     }
 
 
-    public void readyShoot() {
-        this.bowCamera.SetCameraFieldOfViewRecord(60);
-        this.ready();
-    }
-
     void shoot() {
     void shoot() {
-        // 筛选出一个稳定的发射角度
-        // #region 
-        //     bool useAxisData = false;//表示是否使用了九轴原始数据
-        //     Quaternion absolute_rotation = this.bowCamera.transform.rotation;
-        //     Quaternion final_rotation = this.bowCamera.transform.rotation;
-        //     if (recordCount >= recordRotations.Length) {
-        //         for (int i = 0; i < recordRotationVars.Length; i++) {
-        //             recordRotationVars[i] = Quaternion.Angle(recordRotations[i], recordRotations[i + 1]);
-        //         }
-        //         int startCheckIndex = 5;
-        //         int checkAfterCount = 5;
-        //         float min_wave = float.MaxValue;
-        //         for (int i = startCheckIndex; i < recordRotationVars.Length - checkAfterCount; i++)
-        //         {
-        //             float wave = 0;
-        //             for (int j = i; j <= i + checkAfterCount; j++)
-        //             {
-        //                 wave += recordRotationVars[j];
-        //             }
-        //             if (wave < min_wave)
-        //             {
-        //                 min_wave = wave;
-        //                 int best_rotation_index = i;
-        //                 absolute_rotation = recordRotations[best_rotation_index];
-        //                 best_rotation_index -= this.shootBackTime;
-        //                 if (best_rotation_index < 0) best_rotation_index = 0;
-        //                 final_rotation = recordRotations[best_rotation_index];
-        //                 useAxisData = true;
-        //             }
-        //         }
-        //         if (useAxisData) {//坐标轴换算,原始九轴数据直接用可能会出问题,比如相机的父节点Rotation不为identity时
-        //             Quaternion baseQuat = GameMgr.ins.transform.rotation;
-        //             absolute_rotation = baseQuat * absolute_rotation;
-        //             final_rotation = baseQuat * final_rotation;
-        //         }
-        //     }
-        // #endregion
         #region 
         #region 
             Quaternion absolute_rotation = this.bowCamera.transform.rotation;
             Quaternion absolute_rotation = this.bowCamera.transform.rotation;
             Quaternion final_rotation = this.bowCamera.transform.rotation;
             Quaternion final_rotation = this.bowCamera.transform.rotation;
@@ -242,15 +205,9 @@ public class ArmBow : MonoBehaviour
         GameEventCenter.ins.onBowArrowShootOut?.Invoke(this, arrowComp);
         GameEventCenter.ins.onBowArrowShootOut?.Invoke(this, arrowComp);
 
 
         AudioMgr.ins.PlayShoot(AudioMgr.GetAudioSource(arrowCopy));
         AudioMgr.ins.PlayShoot(AudioMgr.GetAudioSource(arrowCopy));
-        // this.gameObject.SetActive(false);
         if (AimHandler.ins) AimHandler.ins.BanControlObjRotate(true);
         if (AimHandler.ins) AimHandler.ins.BanControlObjRotate(true);
     }
     }
 
 
-    public void OnEnable() 
-    {
-        AudioMgr.GetAudioSource(this.gameObject).clip = null;
-    }
-
     public void Hide()
     public void Hide()
     {
     {
         this.transform.localScale = Vector3.zero;
         this.transform.localScale = Vector3.zero;
@@ -260,26 +217,4 @@ public class ArmBow : MonoBehaviour
     {
     {
         this.transform.localScale = new Vector3(1, 1, 1);
         this.transform.localScale = new Vector3(1, 1, 1);
     }
     }
-
-    public bool IsCanShoot()
-    {
-        return canShoot;
-    }
-
-    public void mouseDown() 
-    {
-        if (!this.readying) return;
-        if (this.pulling || this.canShoot) return;
-        this.idleToADS();
-    }
-
-    public void mouseUp() 
-    {
-        if (!this.readying) return;
-        if (this.pulling) {
-            this.idle();
-        } else if (this.canShoot) {
-            this.ADS_fire();
-        }
-    }
 }
 }

+ 12 - 1
Assets/BowArrow/Scripts/Game/Arrow.cs

@@ -1,4 +1,6 @@
 using System;
 using System;
+using System.Collections;
+using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine;
 using DG.Tweening;
 using DG.Tweening;
 /* 箭对象 */
 /* 箭对象 */
@@ -36,12 +38,17 @@ public class Arrow : MonoBehaviour
     [NonSerialized] public ArrowCamera arrowCameraComp;
     [NonSerialized] public ArrowCamera arrowCameraComp;
     public System.Action onDoNextShoot;
     public System.Action onDoNextShoot;
 
 
+    public static HashSet<Arrow> arrowSet = new HashSet<Arrow>();
+
     void Awake()
     void Awake()
     {
     {
+        arrowSet.Add(this);
         GameMgr.ins.gameMode.PauseTimeCounting(this);
         GameMgr.ins.gameMode.PauseTimeCounting(this);
+        this.transform.Find("Head/_hunse_jian").gameObject.layer = 0;
     }
     }
 
 
     void OnDestroy() {
     void OnDestroy() {
+        arrowSet.Remove(this);
         GameMgr.ins.gameMode.ResumeTimeCounting(this);
         GameMgr.ins.gameMode.ResumeTimeCounting(this);
     }
     }
 
 
@@ -234,9 +241,13 @@ public class Arrow : MonoBehaviour
             this.UpdateRotate();
             this.UpdateRotate();
         }
         }
     }
     }
-
+    public ArrowSync.SyncData outputSyncData;
     void Update() {
     void Update() {
         UpdateFlyLogic();
         UpdateFlyLogic();
+        if (GlobalData.pkMatchType == PKMatchType.OnlinePK) {
+            if (outputSyncData == null) outputSyncData = new ArrowSync.SyncData();
+            outputSyncData.SetData(this);
+        }
     }
     }
 
 
     void FlyTimeOut() {
     void FlyTimeOut() {

+ 62 - 24
Assets/BowArrow/Scripts/Game/ArrowCamera.cs

@@ -9,6 +9,13 @@ public class ArrowCamera : MonoBehaviour
     [System.NonSerialized] public Arrow arrow;
     [System.NonSerialized] public Arrow arrow;
     [System.NonSerialized] public ArrowCameraTemplate arrowCameraTemplate;
     [System.NonSerialized] public ArrowCameraTemplate arrowCameraTemplate;
 
 
+    [System.NonSerialized] public bool isArrowSync = false;
+    [System.NonSerialized] public ArrowSync arrowSync;
+    public void SetArrowSync(ArrowSync arrowSync) {
+        isArrowSync = true;
+        this.arrowSync = arrowSync;
+    }
+
     void Awake()
     void Awake()
     {
     {
         BowCamera.ins.GetComponent<Camera>().enabled = false;
         BowCamera.ins.GetComponent<Camera>().enabled = false;
@@ -17,7 +24,7 @@ public class ArrowCamera : MonoBehaviour
     void Start()
     void Start()
     {
     {
         if (SceneManager.GetActiveScene().name == "Game") {
         if (SceneManager.GetActiveScene().name == "Game") {
-            if (arrow.canUseSideCamera) {
+            if ((isArrowSync && arrowSync.canUseSideCamera) || (!isArrowSync && arrow.canUseSideCamera)) {
                 arrowCameraTemplate = new ArrowCameraTemplate2(this);
                 arrowCameraTemplate = new ArrowCameraTemplate2(this);
             } else {
             } else {
                 arrowCameraTemplate = new ArrowCameraTemplate1(this);  
                 arrowCameraTemplate = new ArrowCameraTemplate1(this);  
@@ -45,7 +52,9 @@ public class ArrowCamera : MonoBehaviour
 class ArrowCameraTemplate3 : ArrowCameraTemplate 
 class ArrowCameraTemplate3 : ArrowCameraTemplate 
 {
 {
     public ArrowCameraTemplate3(ArrowCamera arrowCamera)  : base(arrowCamera) {
     public ArrowCameraTemplate3(ArrowCamera arrowCamera)  : base(arrowCamera) {
-        this.arrowCamera.arrow.activeEffectCyclone(true);
+        if (!arrowCamera.isArrowSync) {
+            this.arrowCamera.arrow.activeEffectCyclone(true);
+        }
     }
     }
     
     
     private bool cameraMoveFinish = false;
     private bool cameraMoveFinish = false;
@@ -134,24 +143,44 @@ class ArrowCameraTemplate2 : ArrowCameraTemplate
 
 
     bool isHit = false;
     bool isHit = false;
     public override void Update() {
     public override void Update() {
-        if (!isHit) {
-            isHit = arrowCamera.arrow.isHit;
-            if (isHit) {
-                this.arrowCamera.transform.SetParent(this.arrowCamera.arrow.transform);
-                arrowCamera.transform.localPosition = new Vector3(-0.3f, 0.2f, -1.3f);
-                arrowCamera.transform.LookAt(this.arrowCamera.arrow.Head());
-                Sequence seq = DOTween.Sequence();
-                seq.PrependInterval(2.2f);
-                seq.AppendCallback(delegate() {
-                    this.arrowCamera.arrow.nextShoot();
-                    this.arrowCamera.arrow.enabled = false;
-                    GameObject.Destroy(this.arrowCamera.gameObject);
-                });
-                return;
+        if (arrowCamera.isArrowSync) {
+            if (!isHit) {
+                isHit = arrowCamera.arrowSync.isHit;
+                if (isHit) {
+                    this.arrowCamera.transform.SetParent(this.arrowCamera.arrowSync.transform);
+                    arrowCamera.transform.localPosition = new Vector3(-0.3f, 0.2f, -1.3f);
+                    arrowCamera.transform.LookAt(this.arrowCamera.arrowSync.Head());
+                    Sequence seq = DOTween.Sequence();
+                    seq.PrependInterval(2.2f);
+                    seq.AppendCallback(delegate() {
+                        GameObject.Destroy(this.arrowCamera.gameObject);
+                    });
+                    return;
+                }
+            }
+            if (!arrowCamera.arrowSync) {
+                GameObject.Destroy(this.arrowCamera.gameObject);
+            }
+        } else {
+            if (!isHit) {
+                isHit = arrowCamera.arrow.isHit;
+                if (isHit) {
+                    this.arrowCamera.transform.SetParent(this.arrowCamera.arrow.transform);
+                    arrowCamera.transform.localPosition = new Vector3(-0.3f, 0.2f, -1.3f);
+                    arrowCamera.transform.LookAt(this.arrowCamera.arrow.Head());
+                    Sequence seq = DOTween.Sequence();
+                    seq.PrependInterval(2.2f);
+                    seq.AppendCallback(delegate() {
+                        this.arrowCamera.arrow.nextShoot();
+                        this.arrowCamera.arrow.enabled = false;
+                        GameObject.Destroy(this.arrowCamera.gameObject);
+                    });
+                    return;
+                }
+            }
+            if (!arrowCamera.arrow) {
+                GameObject.Destroy(this.arrowCamera.gameObject);
             }
             }
-        }
-        if (!arrowCamera.arrow) {
-            GameObject.Destroy(this.arrowCamera.gameObject);
         }
         }
     }
     }
 }
 }
@@ -159,7 +188,9 @@ class ArrowCameraTemplate2 : ArrowCameraTemplate
 class ArrowCameraTemplate1 : ArrowCameraTemplate 
 class ArrowCameraTemplate1 : ArrowCameraTemplate 
 {
 {
     public ArrowCameraTemplate1(ArrowCamera arrowCamera)  : base(arrowCamera) {
     public ArrowCameraTemplate1(ArrowCamera arrowCamera)  : base(arrowCamera) {
-        this.arrowCamera.arrow.activeEffectCyclone(true);
+        if (!arrowCamera.isArrowSync) {
+            this.arrowCamera.arrow.activeEffectCyclone(true);
+        }
     }
     }
     
     
     private bool cameraMoveFinish = false;
     private bool cameraMoveFinish = false;
@@ -172,7 +203,8 @@ class ArrowCameraTemplate1 : ArrowCameraTemplate
         }
         }
         Transform cameraT = this.arrowCamera.transform;
         Transform cameraT = this.arrowCamera.transform;
         Vector3 cameraPosition = cameraT.localPosition;
         Vector3 cameraPosition = cameraT.localPosition;
-        if (this.arrowCamera.arrow.isHit) {
+        if ((!this.arrowCamera.isArrowSync && this.arrowCamera.arrow.isHit) || 
+            (this.arrowCamera.isArrowSync && this.arrowCamera.arrowSync.isHit)) {
             cameraPosition = Vector3.Lerp(cameraPosition, cameraFinalPosition, Time.deltaTime * 8);
             cameraPosition = Vector3.Lerp(cameraPosition, cameraFinalPosition, Time.deltaTime * 8);
             float d = Vector3.Distance(cameraPosition, cameraFinalPosition);
             float d = Vector3.Distance(cameraPosition, cameraFinalPosition);
             if (d < 0.001f) {
             if (d < 0.001f) {
@@ -180,15 +212,21 @@ class ArrowCameraTemplate1 : ArrowCameraTemplate
                 Sequence seq = DOTween.Sequence();
                 Sequence seq = DOTween.Sequence();
                 seq.AppendInterval(2.2f);
                 seq.AppendInterval(2.2f);
                 seq.AppendCallback(delegate() {
                 seq.AppendCallback(delegate() {
-                    this.arrowCamera.arrow.nextShoot();
-                    this.arrowCamera.arrow.enabled = false;
+                    if (!arrowCamera.isArrowSync) {
+                        this.arrowCamera.arrow.nextShoot();
+                        this.arrowCamera.arrow.enabled = false;
+                    }
                     GameObject.Destroy(this.arrowCamera.gameObject);
                     GameObject.Destroy(this.arrowCamera.gameObject);
                 });
                 });
             }
             }
         } else {
         } else {
             cameraPosition = Vector3.Lerp(cameraPosition, cameraToRunPosition, Time.deltaTime * 6);
             cameraPosition = Vector3.Lerp(cameraPosition, cameraToRunPosition, Time.deltaTime * 6);
         }
         }
-        cameraT.LookAt(this.arrowCamera.arrow.Head());
+        if (this.arrowCamera.isArrowSync) {
+            cameraT.LookAt(this.arrowCamera.arrowSync.Head());
+        } else {
+            cameraT.LookAt(this.arrowCamera.arrow.Head());
+        }
         cameraT.localPosition = cameraPosition;
         cameraT.localPosition = cameraPosition;
     }
     }
 }
 }

+ 5 - 5
Assets/BowArrow/Scripts/Game/BowCamera.cs

@@ -26,8 +26,8 @@ public class BowCamera : MonoBehaviour
     JC.Unity.TouchChecker touchChecker = new JC.Unity.TouchChecker();
     JC.Unity.TouchChecker touchChecker = new JC.Unity.TouchChecker();
     //触摸模式开关
     //触摸模式开关
     public static bool isTouchMode = true;
     public static bool isTouchMode = true;
-    //禁止弓镜头被用户输入控制
-    [NonSerialized] public bool banUserControl = false;
+    //禁止逻辑,只用于同步状态和渲染,目前用于联机
+    [NonSerialized] public bool banLogic = false;
     private static BowCamera _ins;
     private static BowCamera _ins;
     public static BowCamera ins {
     public static BowCamera ins {
         get {
         get {
@@ -45,7 +45,7 @@ public class BowCamera : MonoBehaviour
 
 
     void Start() {
     void Start() {
         touchChecker.onMoved += delegate(Touch t, bool isOnUI) {
         touchChecker.onMoved += delegate(Touch t, bool isOnUI) {
-            if (banUserControl) return;
+            if (banLogic) return;
             if (isOnUI) return;
             if (isOnUI) return;
             //触摸控制镜头和拉弓射箭
             //触摸控制镜头和拉弓射箭
             this.localEulerAngles.x = Mathf.Clamp(this.localEulerAngles.x - t.deltaPosition.y * Time.deltaTime * 5, -36, 36);
             this.localEulerAngles.x = Mathf.Clamp(this.localEulerAngles.x - t.deltaPosition.y * Time.deltaTime * 5, -36, 36);
@@ -53,7 +53,7 @@ public class BowCamera : MonoBehaviour
             this.transform.localEulerAngles = this.localEulerAngles; 
             this.transform.localEulerAngles = this.localEulerAngles; 
         };
         };
         touchChecker.onEnded += delegate(Touch t, bool isOnUI) {
         touchChecker.onEnded += delegate(Touch t, bool isOnUI) {
-            if (banUserControl) return;
+            if (banLogic) return;
             if (!isOnUI) armBow.ADS_fire();
             if (!isOnUI) armBow.ADS_fire();
         };
         };
     }
     }
@@ -65,7 +65,7 @@ public class BowCamera : MonoBehaviour
             cameraComp.fieldOfView = cameraFieldOfView;
             cameraComp.fieldOfView = cameraFieldOfView;
         }
         }
 
 
-        if (banUserControl) return;
+        if (banLogic) return;
 
 
         //满足以下条件则阻止控制输入
         //满足以下条件则阻止控制输入
         if (GameMgr.ins.gameOver) {
         if (GameMgr.ins.gameOver) {

+ 11 - 1
Assets/BowArrow/Scripts/GlobalData.cs

@@ -5,12 +5,22 @@ using UnityEngine;
 /** 全局游戏数据 */
 /** 全局游戏数据 */
 public class GlobalData
 public class GlobalData
 {
 {
+    public static PKMatchType pkMatchType = PKMatchType.None;
     //本地双人PK,双方选择的角色ID
     //本地双人PK,双方选择的角色ID
     public static int[] localPK_playerRoleIDs = new int[] {1, 2};
     public static int[] localPK_playerRoleIDs = new int[] {1, 2};
-    public static PKMatchType pkMatchType = PKMatchType.None;
+    //双人PK匹配结果
+    public static int matchRoomType = 0; //Pk匹配房间类型
+    public static int roomID;
+    public static int playerIndexInRoom;
+    public static List<MatchPlayerInfo> matchPlayerInfos;
 }
 }
 public enum PKMatchType {
 public enum PKMatchType {
     None, //不是PK,就是单击单人
     None, //不是PK,就是单击单人
     LocalPK, //本地PK
     LocalPK, //本地PK
     OnlinePK //联网PK4444
     OnlinePK //联网PK4444
 }
 }
+ public class MatchPlayerInfo {
+    public int playerID;
+    public int avatarID;
+    public string nickname;
+}

+ 8 - 0
Assets/BowArrow/Scripts/Manager/GameMode/OnlineObject.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: bbc9f070706b54a449609d1e2b10796e
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 5 - 0
Assets/BowArrow/Scripts/Manager/GameMode/OnlineObject/ArmBowSyncData.cs

@@ -0,0 +1,5 @@
+using System;
+public class ArmBowSyncData
+{
+    
+}

+ 11 - 0
Assets/BowArrow/Scripts/Manager/GameMode/OnlineObject/ArmBowSyncData.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2ec188ae1fb17024ca386539f6689756
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 83 - 0
Assets/BowArrow/Scripts/Manager/GameMode/OnlineObject/ArrowSync.cs

@@ -0,0 +1,83 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class ArrowSync : MonoBehaviour
+{
+    void Awake()
+    {
+        this.transform.Find("Head/_hunse_jian").gameObject.layer = 0;
+    }
+
+    void Update()
+    {
+        transform.position = Vector3.Lerp(transform.position, position, Time.deltaTime * 15);
+        Head().position = transform.position;
+        transform.rotation = Quaternion.Lerp(transform.rotation, rotation, Time.deltaTime * 15);     
+    }
+
+    public Transform Head() {
+        return transform.Find("Head");
+    }
+
+    Quaternion rotation;
+    Vector3 position;
+    [System.NonSerialized] public bool isHit;
+    [System.NonSerialized] public bool canUseSideCamera;
+    [System.NonSerialized] public bool hasSetSyncData = false; //外部运算用的
+    public void SetSyncData(SyncData syncData, bool apply = false) {
+        rotation.x = syncData.rx;
+        rotation.y = syncData.ry;
+        rotation.z = syncData.rz;
+        rotation.w = syncData.rw;
+        position.x = syncData.px;
+        position.y = syncData.py;
+        position.z = syncData.pz;
+        canUseSideCamera = syncData.cs;
+        isHit = syncData.ih;
+        if (apply) {
+            transform.position = position;
+            transform.rotation = rotation;
+            //激活镜头
+            Transform cameraTF = this.transform.Find("Camera");
+            cameraTF.gameObject.SetActive(true);
+            ArrowCamera arrowCameraComp = cameraTF.gameObject.AddComponent<ArrowCamera>();
+            arrowCameraComp.SetArrowSync(this);
+            //射出的声音
+            AudioMgr.ins.PlayShoot(AudioMgr.GetAudioSource(this.gameObject));
+        }
+    }
+
+    public class SyncData {
+        [System.NonSerialized] public bool inited;
+        static int autoID;
+        public int id;
+        public float rx;
+        public float ry;
+        public float rz;
+        public float rw;
+        public float px;
+        public float py;
+        public float pz;
+        public bool cs;
+        public bool ih;
+        public void SetData(Arrow arrow) {
+            Quaternion r = arrow.transform.rotation;
+            Vector3 p = arrow.Head().transform.position;
+            rx = r.x;
+            ry = r.y;
+            rz = r.z;
+            rw = r.w;
+            px = p.x;
+            py = p.y;
+            pz = p.z;
+            cs = arrow.canUseSideCamera;
+            ih = arrow.isHit;
+            if (!inited) {
+                id = autoID++;
+                if (autoID > 1000) autoID = 0;
+            }
+            inited = true;
+        }
+    }
+}

+ 11 - 0
Assets/BowArrow/Scripts/Manager/GameMode/OnlineObject/ArrowSync.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4f84cc52410075c4e97b7a4abb59eaf4
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 345 - 3
Assets/BowArrow/Scripts/Manager/GameMode/PKGameMode_OnlinePK.cs

@@ -3,13 +3,355 @@ using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine;
 using UnityEngine.UI;
 using UnityEngine.UI;
 using DG.Tweening;
 using DG.Tweening;
+using Newtonsoft.Json;
 
 
 /**双人PK模式 */
 /**双人PK模式 */
-public class PKGameMode_OnlinePK : PKGameMode {
+public class PKGameMode_OnlinePK : GameMode {
     SocketPlayer socketPlayer;
     SocketPlayer socketPlayer;
+    public int myPlayerIndex = -111;
+    public bool IsMyPlayerInited() {
+        return myPlayerIndex >= 0;
+    }
+    public bool IsMyPlayerRunning() {
+        return myPlayerIndex == gameLogic.currentPlayerIndex;
+    }
 
 
     public PKGameMode_OnlinePK(GameMgr gameMgr) : base(gameMgr) {
     public PKGameMode_OnlinePK(GameMgr gameMgr) : base(gameMgr) {
-        socketPlayer = new GameObject().AddComponent<SocketPlayer>();
-        socketPlayer.gameMode = this;
+        GlobalData.pkMatchType = PKMatchType.OnlinePK;
+        myPlayerIndex = GlobalData.playerIndexInRoom;
+
+        gameLogic.InitAppearPlayerIndexes();
+        gameLogic.SetCurrentPlayerIndexToNext();
+
+        //记录可射击的靶子
+        targetBody = GameObject.Find("GameArea/TargetObject/TargetBody").GetComponent<TargetBody>();
+        GameObject.FindObjectOfType<ArmBow>().validTargets.Add(targetBody);
+        //添加游戏界面
+        GameObject view = Resources.Load<GameObject>("Prefabs/Views/PKGameView");
+        GameObject.Instantiate(view);
+        //禁止动作-相机和手臂
+        BanBowReady();
+
+        AutoSwitchBanUserControlBow();
+
+        // socketPlayer = new GameObject("SocketPlayer").AddComponent<SocketPlayer>();
+        socketPlayer = GameObject.Find("SocketPlayer").GetComponent<SocketPlayer>();
+        socketPlayer.onReceivePKGameData = onReceivePKGameData;
+    }
+    
+    Quaternion bowTargetQua; 
+    bool hasBowTargBtQua;
+    void onReceivePKGameData(string key, string data) {
+        if (key == "logic") {
+            GameLogic gameLogic = JsonConvert.DeserializeObject<GameLogic>(data);
+            if (
+                (gameLogic.nextPlayerExcuteID == this.gameLogic.nextPlayerExcuteID && myPlayerIndex != gameLogic.currentPlayerIndex) ||
+                (gameLogic.nextPlayerExcuteID > this.gameLogic.nextPlayerExcuteID)
+            ) {
+                this.gameLogic = gameLogic;
+                AutoSwitchBanUserControlBow();
+            }
+        }
+        if (key == "bow") {
+            if (!IsMyPlayerRunning()) {
+                string[] quaStr = data.Split(',');
+                if (quaStr.Length == 5) {
+                    bowTargetQua.x = float.Parse(quaStr[0]);
+                    bowTargetQua.y = float.Parse(quaStr[1]);
+                    bowTargetQua.z = float.Parse(quaStr[2]);
+                    bowTargetQua.w = float.Parse(quaStr[3]);
+                    hasBowTargBtQua = true;
+                    ArmBow.ins.phase = int.Parse(quaStr[4]);
+                } 
+            }
+        }
+        if (key == "arrow") {
+            List<ArrowSync.SyncData> arrowSyncDataList = JsonConvert.DeserializeObject<List<ArrowSync.SyncData>>(data);
+            foreach (var item in arrowSyncMap) {
+                item.Value.hasSetSyncData = false;
+            }
+            GameObject arrowPrefab = ArmBow.ins.arrow;
+            foreach (var item in arrowSyncDataList) {
+                ArrowSync arrowSync;
+                arrowSyncMap.TryGetValue(item.id, out arrowSync);
+                if (arrowSync == null) {
+                    GameObject arrowObj = GameObject.Instantiate(arrowPrefab);
+                    GameObject.Destroy(arrowObj.GetComponent<BoxCollider>());
+                    arrowSync = arrowObj.AddComponent<ArrowSync>();
+                    arrowSync.SetSyncData(item, true);
+                    arrowSyncMap[item.id] = arrowSync;
+                    arrowObj.SetActive(true);
+                } else {
+                    arrowSync.SetSyncData(item);
+                }
+                arrowSync.hasSetSyncData = true;
+            }
+            List<int> removeIDs = null;
+            foreach (var item in arrowSyncMap) {
+                if (!item.Value.hasSetSyncData) {
+                    if (removeIDs == null) removeIDs = new List<int>();
+                    removeIDs.Add(item.Key);
+                } 
+            }
+            if (removeIDs != null) {
+                foreach (var id in removeIDs) {
+                    ArrowSync arrowSync = arrowSyncMap[id];
+                    arrowSyncMap.Remove(id);
+                    if (arrowSync && arrowSync.gameObject) {
+                        GameObject.Destroy(arrowSync.gameObject);
+                    }
+                }
+            }
+        }
+        if (key == "score") {
+            HitTargetNumber.Create(float.Parse(data));
+            AudioMgr.ins.PlayHit(AudioMgr.GetAudioSource(TargetBody.ins.gameObject));
+        }
+    }
+
+    void AutoSwitchBanUserControlBow() {
+        BowCamera.ins.banLogic = ArmBow.ins.banLogic = !IsMyPlayerRunning();
+    }
+    
+    //记录可射击的靶子
+    TargetBody targetBody;
+
+    bool hasStart = false;
+    public override void Start() {
+        hasStart = true;
+        TargetView.ins.Show(true);
+    }
+
+    void AddReadyView() 
+    {
+        GameObject view = Resources.Load<GameObject>("Prefabs/Views/PKGameReadyView");
+        GameObject.Instantiate(view);
+    }
+
+    public override void HitTarget(float score) {
+        gameLogic.HitTarget(score);
+        HitTargetNumber.Create(score);
+        scoreWillSend = score.ToString();
+    }
+
+    public override bool DoNextShoot() {
+        return gameLogic.DoNextShoot(this); 
+    }
+
+    public override object[] Settle() {
+        return gameLogic.gameRes;
+    }
+    float uploadGameDataTime = 0;
+    float uploadBowTime = 0;
+    public override void Update() {
+        if (!IsMyPlayerInited()) return;
+        if (!hasStart) return;
+        AutoSwitchBanUserControlBow();
+        if (IsMyPlayerRunning()) {
+            gameLogic.Update(this);   
+            upload1();
+        }
+        upload2();
+        gameDisplay.Update(this);
+    }
+    Dictionary<int, ArrowSync> arrowSyncMap = new Dictionary<int, ArrowSync>();
+    void upload1() {
+        uploadBowTime -= Time.deltaTime;
+        if (uploadBowTime <= 0) {
+            uploadBowTime = 0.1f;
+            Quaternion qua = BowCamera.ins.transform.rotation;
+            socketPlayer.UploadPKGameData("bow", qua.x + "," + qua.y + "," + qua.z + "," + qua.w + "," + ArmBow.ins.phase);
+        }
+    }
+    string scoreWillSend = null;
+    void upload2() {
+        uploadGameDataTime -= Time.deltaTime;
+        if (uploadGameDataTime <= 0) {
+            uploadGameDataTime = 0.05f;
+            socketPlayer.UploadPKGameData("logic", gameLogic);
+
+            List<ArrowSync.SyncData> arrowSyncDataList = new List<ArrowSync.SyncData>();
+            foreach (var item in Arrow.arrowSet) {
+                if (item.outputSyncData == null || !item.outputSyncData.inited) continue;
+                arrowSyncDataList.Add(item.outputSyncData);
+            }
+            socketPlayer.UploadPKGameData("arrow", arrowSyncDataList);
+            if (scoreWillSend != null) {
+                socketPlayer.UploadPKGameData("score", scoreWillSend);
+                scoreWillSend = null;
+            }
+        }
+    }
+
+    public override void onBowReady() {
+        if (!IsMyPlayerRunning()) return;
+        gameLogic.singleShootReadyTime = gameLogic.singleShootReadyMaxTime;
+        gameLogic.singleShootTimeRunning = true;
+    }
+
+    public override void onBowShoot() {
+        if (!IsMyPlayerRunning()) return;
+        gameLogic.singleShootTimeRunning = false;   
+    }
+
+    //gamelogic-data
+    public GameLogic gameLogic = new GameLogic();
+    public class GameLogic {
+        public int currentPlayerIndex = 0;
+        public int[] totalScores = {0, 0};
+        public float[] currentScores = {0, 0};
+        public int round = 1;
+        public int maxRound = 5;
+        public int[] shootCount = {0, 0};
+        public int maxShootCount = 3;
+        public float singleShootReadyTime = 20;
+        public float singleShootReadyMaxTime = 20;
+        public bool singleShootTimeRunning = false;
+        public string[] gameRes = {"平局", "平局"};
+        public bool gameEnd = false;
+        //玩家出场顺序
+        public Queue<int> appearPlayerIndexes = new Queue<int>();
+        public int[] sequencePlayerIndexes = new int[]{0, 1};
+        public int nextPlayerExcuteID = 0;
+        public void InitAppearPlayerIndexes()
+        {
+            if (round >= 2)
+            {
+                if (totalScores[0] < totalScores[1])
+                {
+                    sequencePlayerIndexes = new int[]{0, 1};
+                }
+                else if (totalScores[1] < totalScores[0])
+                {
+                    sequencePlayerIndexes = new int[]{1, 0};
+                }
+            }
+            for (int i = 0; i < maxShootCount; i++) {
+                appearPlayerIndexes.Enqueue(sequencePlayerIndexes[0]);
+                appearPlayerIndexes.Enqueue(sequencePlayerIndexes[1]);
+            }
+        }
+        public void SetCurrentPlayerIndexToNext() {
+            currentPlayerIndex = appearPlayerIndexes.Dequeue();
+            nextPlayerExcuteID++;
+        }
+        public void Update(PKGameMode_OnlinePK gm) {
+            if (singleShootTimeRunning && !gm.pauseTimeCounting) {
+                singleShootReadyTime -= Time.deltaTime;
+                if (singleShootReadyTime <= 0) {
+                    singleShootReadyTime = 0;
+                    singleShootTimeRunning = false;
+                    HitTarget(0);
+                    // BanBowReady();
+                    // //超时显示
+                    // Text timeoutText = PKGameView.ins.transform.Find("TimeoutText").GetComponent<Text>();
+                    // Sequence seq = DOTween.Sequence();
+                    // seq.Append(timeoutText.DOFade(1, 0.5f));
+                    // seq.AppendInterval(1);
+                    // seq.Append(timeoutText.DOFade(0, 0.5f));
+                    // seq.AppendCallback(delegate(){
+                    //     if (DoNextShoot()) {
+                    //         UnbanBowReady();
+                    //     }
+                    // });
+                    DoNextShoot(gm);
+                }
+            }
+        }
+        public void HitTarget(float score) {
+            currentScores[currentPlayerIndex] += score;
+            shootCount[currentPlayerIndex]++;
+        }
+        public bool DoNextShoot(PKGameMode_OnlinePK gm) {
+            if (gm.gameMgr.gameOver) return false;
+            bool nextRound = false;
+            if (shootCount[0] == maxShootCount && shootCount[1] == maxShootCount ) {
+                shootCount = new int[]{0, 0};
+                nextRound = true;
+                //更新总比分
+                if (currentScores[0] == currentScores[1]) {
+                    totalScores[0] += 1;
+                    totalScores[1] += 1;
+                } else if (currentScores[0] > currentScores[1]) {
+                    totalScores[0] += 2;
+                } else if (currentScores[0] < currentScores[1]) {
+                    totalScores[1] += 2;
+                }
+                //根据总比分判断游戏是否结束
+                if (totalScores[0] == totalScores[1]) {
+                    if (round == maxRound) {
+                        if (round == 5) {
+                            maxShootCount = 1;
+                            maxRound = 6;
+                        } else {
+                            gameEnd = true;    
+                            gameRes = new string[]{"平局", "平局"};
+                        }
+                    }
+                } else if (totalScores[0] >= 6 && totalScores[0] > totalScores[1]) {
+                    gameEnd = true;
+                    gameRes = new string[]{"胜利", "失败"};
+                } else if (totalScores[1] >= 6 && totalScores[1] > totalScores[0]) {
+                    gameEnd = true;
+                    gameRes = new string[]{"失败", "胜利"};
+                }
+            }
+            if (gameEnd) {
+                return false;
+            } else {
+                //进入下一回合?
+                if (nextRound) {
+                    round++;
+                    currentScores[0] = currentScores[1] = 0;
+                    InitAppearPlayerIndexes();
+                }
+                //本轮玩家登记
+                SetCurrentPlayerIndexToNext();
+                gm.BanBowReady();
+            }
+            return true; 
+        }
+    }
+    //game-display
+    public GameDisplay gameDisplay = new GameDisplay();
+    public class GameDisplay {
+        readonly float[] targetDistancesOnRound = {10, 20, 30, 50, 70, 70};
+        public int[] playerRoleIDs = {1, 2};
+        public int showRoundValueOnReadyView = 0;
+
+        #region 用于控制显示更新的变量
+            int round = 0;
+            int nextPlayerExcuteID = 0;
+            bool gameEnd = false;
+        #endregion
+
+        public void Update(PKGameMode_OnlinePK gm) {
+            if (round != gm.gameLogic.round) {
+                round = gm.gameLogic.round;
+                gm.targetBody.SetDistance(targetDistancesOnRound[round - 1]);
+            }
+            if (nextPlayerExcuteID != gm.gameLogic.nextPlayerExcuteID) {
+                nextPlayerExcuteID = gm.gameLogic.nextPlayerExcuteID;
+                gm.BanBowReady();
+                gm.AddReadyView();
+                //清除箭矢
+                foreach (var arrow in Arrow.arrowSet) {
+                    try {
+                        GameObject.Destroy(arrow.gameObject);
+                    } catch (UnityException e) {
+                        Debug.Log("Delete Arrow Error\n" + e.Message);
+                    }
+                }
+            }
+            if (!gameEnd && gm.gameLogic.gameEnd) {
+                gameEnd = true;
+                gm.gameMgr.StopGame();
+                GameObject view = Resources.Load<GameObject>("Prefabs/Views/PKGameSettleView");
+                GameObject.Instantiate(view);
+            }
+            if (!gm.IsMyPlayerRunning() && gm.hasBowTargBtQua) {
+                BowCamera.ins.transform.rotation = Quaternion.Lerp(BowCamera.ins.transform.rotation, gm.bowTargetQua, Time.deltaTime * 12);
+            }
+        }
     }
     }
 }
 }

+ 2 - 0
Assets/BowArrow/Scripts/Manager/LoginMgr.cs

@@ -243,8 +243,10 @@ public class UserInfos {
 
 
 [Serializable]
 [Serializable]
 public class UserInfo {
 public class UserInfo {
+    public int id;
     public string user = "";
     public string user = "";
     public string pwd = "";
     public string pwd = "";
+    public int avatarID = 0;
     public string nickname = "";
     public string nickname = "";
     public string phone = "";
     public string phone = "";
     public int gender = 0;
     public int gender = 0;

+ 48 - 59
Assets/BowArrow/Scripts/Network/SocketPlayer.cs

@@ -1,91 +1,80 @@
 using System;
 using System;
+using System.Collections;
+using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine;
 using UnityEngine.UI;
 using UnityEngine.UI;
 
 
 public class SocketPlayer : JC.SocketIO.SocketIOClient
 public class SocketPlayer : JC.SocketIO.SocketIOClient
 {
 {
-    public PKGameMode_OnlinePK gameMode;
-
+    void Awake() 
+    {
+        InitDestroySelf();
+    }
+    void InitDestroySelf() {
+        GlobalEventCenter.ins.onGameSceneDestroy += DestroySelf;
+    }
+    void DestroySelf() {
+        GlobalEventCenter.ins.onGameSceneDestroy -= DestroySelf;
+        if (gameObject) Destroy(gameObject);
+    }
     void Start()
     void Start()
     {
     {
-        connectServer("http://192.168.101.14:8000/socket.io/");
+        connectServer("ws://192.168.101.14:8000/SmartBowGameServer");
     }
     }
-
+    public Action onLoad_;
     public override void onLoad()
     public override void onLoad()
     {
     {
         Debug.Log("onLoad");
         Debug.Log("onLoad");
-
-        call("RandomMatchRoom", 0);
+        onLoad_?.Invoke();
     }
     }
-
     public override void onReload()
     public override void onReload()
     {
     {
         Debug.Log("onReload");
         Debug.Log("onReload");
     }
     }
-
     public override void onDestroy()
     public override void onDestroy()
     {
     {
         Debug.Log("onDestroy");
         Debug.Log("onDestroy");
     }
     }
-
     public override void onMiss()
     public override void onMiss()
     {
     {
         Debug.Log("onMiss");
         Debug.Log("onMiss");
     }
     }
 
 
-    bool isMyTime = false;
-
-    float uploadTimeCountDown = 0;
-
-    void Update() {
-        if (playerIndex < 0) return;
-        isMyTime = playerIndex == gameMode.currentPlayerIndex;
-        BowCamera.ins.banUserControl = !isMyTime;
-
-        if (isMyTime) {
-            uploadTimeCountDown -= Time.deltaTime;
-            if (uploadTimeCountDown <= 0) {
-                uploadTimeCountDown = 1f / 30;
-                UploadPKGameData();
+    //主动接口
+    public void UploadPlayerInfo() {
+        UserInfo userInfo = LoginMgr.myUserInfo;
+        userInfo.id = int.Parse(JC.CS.Utility.GetTimestamp().ToString().Substring(4));
+        call("UploadPlayerInfo", userInfo.id, "P" + userInfo.id,  UnityEngine.Random.Range(0, 7));
+    }
+    public void AgreeStartGame() {
+        call("AgreeStartGame");
+    }
+    public Action onAgreeStartGame;
+    public void OnAgreeStartGame() {
+        onAgreeStartGame?.Invoke();
+    }
+    //随机匹配
+    public void RandomMatchRoom() {
+        call("RandomMatchRoom", GlobalData.matchRoomType);
+    }
+    public Action onMatchSuccess; 
+    public void OnMatchSuccess(List<MatchPlayerInfo> matchPlayerInfos, int roomID) {
+        GlobalData.roomID = roomID;
+        GlobalData.matchPlayerInfos = matchPlayerInfos;
+        for (int i = 0; i < matchPlayerInfos.Count; i++) {
+            if (matchPlayerInfos[i].playerID == LoginMgr.myUserInfo.id) {
+                GlobalData.playerIndexInRoom = i;
             }
             }
-        } else {
-            BowCamera.ins.transform.rotation = Quaternion.Lerp(BowCamera.ins.transform.rotation, bowCameraTargetRotation, Time.deltaTime * 10);
         }
         }
+        onMatchSuccess?.Invoke();
     }
     }
-
-    PKGameData pkGameDataSend = new PKGameData();
-
-    void UploadPKGameData() {
-        Quaternion bowCameraR = BowCamera.ins.transform.rotation;
-        pkGameDataSend.rx = bowCameraR.x;
-        pkGameDataSend.ry = bowCameraR.y;
-        pkGameDataSend.rz = bowCameraR.z; 
-        pkGameDataSend.rw = bowCameraR.w;
-        call("UploadPKGameData", pkGameDataSend);
-    } 
-
-    Quaternion bowCameraTargetRotation;
-
-    public void OnReceivePKGameData(PKGameData pkGameData) {
-        bowCameraTargetRotation.x = pkGameData.rx;
-        bowCameraTargetRotation.y = pkGameData.ry;
-        bowCameraTargetRotation.z = pkGameData.rz;
-        bowCameraTargetRotation.w = pkGameData.rw;
+    //上传游戏数据
+    public void UploadPKGameData(string key, object data) {
+        if (!isValid) return;
+        call("UploadPKGameData", key, data);
     }
     }
-
-    //被服务器调用接口
-    int roomID;
-    int playerIndex = -1;
-    public void OnJoinRoomSuccess(int roomID, int playerIndex) {
-        this.roomID = roomID;
-        this.playerIndex = playerIndex;
-        Debug.Log("OnJoinRoomSuccess " + roomID + ", " + playerIndex);
+    public Action<string, string> onReceivePKGameData;  
+    public void OnReceivePKGameData(string key, string data) {
+        onReceivePKGameData?.Invoke(key, data);
     }
     }
-}
-
-public class PKGameData {
-    public float rx;
-    public float ry;
-    public float rz;
-    public float rw;
 }
 }

+ 1 - 0
Assets/BowArrow/Scripts/View/PKGameOptionView.cs

@@ -23,6 +23,7 @@ public class PKGameOptionView : MonoBehaviour
                 break;
                 break;
             case "静止靶":
             case "静止靶":
                 if (GlobalData.pkMatchType == PKMatchType.OnlinePK) {
                 if (GlobalData.pkMatchType == PKMatchType.OnlinePK) {
+                    GlobalData.matchRoomType = 0;
                     GameObject.Instantiate(GameObject.Find("WindowViews").transform.Find("PKMatchView").gameObject).SetActive(true);
                     GameObject.Instantiate(GameObject.Find("WindowViews").transform.Find("PKMatchView").gameObject).SetActive(true);
                 } else {
                 } else {
                     GameMgr.gameType = 2;
                     GameMgr.gameType = 2;

+ 71 - 15
Assets/BowArrow/Scripts/View/PKGameReadyView.cs

@@ -7,26 +7,88 @@ using DG.Tweening;
 public class PKGameReadyView : MonoBehaviour
 public class PKGameReadyView : MonoBehaviour
 {
 {
     PKGameMode pKGameMode;
     PKGameMode pKGameMode;
+    PKGameMode_OnlinePK pKGameMode_OnlinePK;
     public bool showRound = false;
     public bool showRound = false;
 
 
+    public bool isDiscarded = false;//丢弃的
+    static PKGameReadyView ins;
+
     void Start()
     void Start()
     {   
     {   
+        if (ins) {
+            ins.isDiscarded = true;
+            Destroy(ins.gameObject);
+        }
+        ins = this;
         GameObject.FindObjectOfType<ArmBow>().Hide();
         GameObject.FindObjectOfType<ArmBow>().Hide();
         
         
-        pKGameMode = (PKGameMode) GameMgr.ins.gameMode;
-        (Sprite avatar, string nickName) = RoleMgr.GetRoleInfo(PKGameMode.playerRoleIDs[pKGameMode.currentPlayerIndex]);
-        this.transform.Find("Panel/Avatar/Sprite").GetComponent<Image>().sprite = avatar;
-        this.transform.Find("Panel/Name").GetComponent<Text>().text = nickName;
+        InitPKGameMode();
+        RenderPlayerInfo();
+        RunAnimation();
+    }
+
+    void OnDestroy()
+    {
+        if (isDiscarded) return;
+        GameObject.FindObjectOfType<ArmBow>().Show();
+        GameMgr.ins.gameMode.UnbanBowReady();
+    }
+
+    void InitPKGameMode() {
+        if (GlobalData.pkMatchType == PKMatchType.LocalPK) {
+            pKGameMode = (PKGameMode) GameMgr.ins.gameMode;
+        }
+        else if (GlobalData.pkMatchType == PKMatchType.OnlinePK) {
+            pKGameMode_OnlinePK = (PKGameMode_OnlinePK) GameMgr.ins.gameMode;
+        }
+    }
+
+    void RenderPlayerInfo() {
+        if (GlobalData.pkMatchType == PKMatchType.LocalPK) {
+            (Sprite avatar, string nickName) = RoleMgr.GetRoleInfo(PKGameMode.playerRoleIDs[pKGameMode.currentPlayerIndex]);
+            this.transform.Find("Panel/Avatar/Sprite").GetComponent<Image>().sprite = avatar;
+            this.transform.Find("Panel/Name").GetComponent<Text>().text = nickName;
+        }
+        else if (GlobalData.pkMatchType == PKMatchType.OnlinePK) {
+            int curPlayerIndex = pKGameMode_OnlinePK.gameLogic.currentPlayerIndex;
+            (Sprite avatar, string nickName) = RoleMgr.GetRoleInfo(GlobalData.matchPlayerInfos[curPlayerIndex].avatarID);
+            this.transform.Find("Panel/Avatar/Sprite").GetComponent<Image>().sprite = avatar;
+            this.transform.Find("Panel/Name").GetComponent<Text>().text = GlobalData.matchPlayerInfos[curPlayerIndex].nickname;
+        }
+    }
+
+    void RunAnimation() {
+        // get data
+        int roundNum = 0;
+        int showRoundValue = 0;
+        System.Action setShowRoundValue = null;
+        if (GlobalData.pkMatchType == PKMatchType.LocalPK) {
+            roundNum = pKGameMode.round;
+            showRoundValue = pKGameMode.showRoundValue;
+            setShowRoundValue = () => {
+                pKGameMode.showRoundValue = roundNum;
+            };
+        }
+        else if (GlobalData.pkMatchType == PKMatchType.OnlinePK) {
+            roundNum = pKGameMode_OnlinePK.gameLogic.round;
+            showRoundValue = pKGameMode_OnlinePK.gameDisplay.showRoundValueOnReadyView;
+            setShowRoundValue = () => {
+                pKGameMode_OnlinePK.gameDisplay.showRoundValueOnReadyView = roundNum;
+            };
+        } else {
+            throw new System.Exception("pkMatchType Error");
+        }
+        // animate
         Image mask = this.transform.Find("Mask").GetComponent<Image>();
         Image mask = this.transform.Find("Mask").GetComponent<Image>();
         Transform panel = this.transform.Find("Panel"); 
         Transform panel = this.transform.Find("Panel"); 
         TextAutoLanguage round = this.transform.Find("Round").GetComponent<TextAutoLanguage>(); 
         TextAutoLanguage round = this.transform.Find("Round").GetComponent<TextAutoLanguage>(); 
         Sequence seq = DOTween.Sequence();
         Sequence seq = DOTween.Sequence();
-        if (pKGameMode.showRoundValue < pKGameMode.round) {
-            pKGameMode.showRoundValue = pKGameMode.round;
+        if (showRoundValue < roundNum) {
+            setShowRoundValue?.Invoke();
             seq.AppendCallback(delegate() {
             seq.AppendCallback(delegate() {
-            round.textFormatArgs = new string[]{pKGameMode.round.ToString()};
-            round.transform.localScale = new Vector3(0, 0, 0);
-            round.gameObject.SetActive(true);
+                round.textFormatArgs = new string[]{roundNum.ToString()};
+                round.transform.localScale = new Vector3(0, 0, 0);
+                round.gameObject.SetActive(true);
             });
             });
             seq.Append(round.transform.DOScale(new Vector3(1.1f, 1.1f, 1f), 0.6f));
             seq.Append(round.transform.DOScale(new Vector3(1.1f, 1.1f, 1f), 0.6f));
             seq.Append(round.transform.DOScale(new Vector3(1, 1, 1), 0.6f));
             seq.Append(round.transform.DOScale(new Vector3(1, 1, 1), 0.6f));
@@ -46,10 +108,4 @@ public class PKGameReadyView : MonoBehaviour
             Destroy(this.gameObject);
             Destroy(this.gameObject);
         });
         });
     }
     }
-
-    void OnDestroy()
-    {
-        GameObject.FindObjectOfType<ArmBow>().Show();
-        pKGameMode.UnbanBowReady();
-    }
 }
 }

+ 25 - 8
Assets/BowArrow/Scripts/View/PKGameSettleView.cs

@@ -6,23 +6,40 @@ using UnityEngine.SceneManagement;
 /* PK模式的结算界面 */
 /* PK模式的结算界面 */
 public class PKGameSettleView : MonoBehaviour
 public class PKGameSettleView : MonoBehaviour
 {
 {
-    PKGameMode pKGameMode;
     void Start()
     void Start()
     {
     {
-        pKGameMode = (PKGameMode) GameMgr.ins.gameMode;
+        GameMode gameMode = GameMgr.ins.gameMode;
         if (PKGameView.ins)
         if (PKGameView.ins)
         {
         {
             PKGameView.ins.gameObject.SetActive(false);
             PKGameView.ins.gameObject.SetActive(false);
         }
         }
-        string[] results = (string[]) GameMgr.ins.gameMode.Settle();
+        string[] results = (string[]) gameMode.Settle();
         for (int i = 1; i <= 2; i++) {
         for (int i = 1; i <= 2; i++) {
-            int playerRoleID = PKGameMode.playerRoleIDs[i - 1];
-            (Sprite avatar, string nickName) = RoleMgr.GetRoleInfo(playerRoleID);
-            this.transform.Find("Avatar" + i + "/Sprite").GetComponent<Image>().sprite = avatar;
-            this.transform.Find("Name" + i).GetComponent<Text>().text = nickName;
+            if (GlobalData.pkMatchType == PKMatchType.OnlinePK) {
+                int playerIndex = i - 1;
+                (Sprite avatar, string nickName) = RoleMgr.GetRoleInfo(GlobalData.matchPlayerInfos[playerIndex].avatarID);
+                nickName = GlobalData.matchPlayerInfos[playerIndex].nickname;
+                this.transform.Find("Avatar" + i + "/Sprite").GetComponent<Image>().sprite = avatar;
+                this.transform.Find("Name" + i).GetComponent<Text>().text = nickName;
+            } else if (GlobalData.pkMatchType == PKMatchType.LocalPK) {
+                (Sprite avatar, string nickName) = RoleMgr.GetRoleInfo(PKGameMode.playerRoleIDs[i - 1]);
+                this.transform.Find("Avatar" + i + "/Sprite").GetComponent<Image>().sprite = avatar;
+                this.transform.Find("Name" + i).GetComponent<Text>().text = nickName;
+            }
             this.transform.Find("Win" + i).gameObject.SetActive(results[i - 1] == "胜利");
             this.transform.Find("Win" + i).gameObject.SetActive(results[i - 1] == "胜利");
             this.transform.Find("Fail" + i).gameObject.SetActive(results[i - 1] == "失败");
             this.transform.Find("Fail" + i).gameObject.SetActive(results[i - 1] == "失败");
-            this.transform.Find("Score" + i + "/Text").GetComponent<Text>().text = pKGameMode.totalScores[i - 1].ToString();
+            if (GlobalData.pkMatchType == PKMatchType.LocalPK) {
+                this.transform.Find("Score" + i + "/Text").GetComponent<Text>().text = ((PKGameMode)gameMode).totalScores[i - 1].ToString();
+            } else if (GlobalData.pkMatchType == PKMatchType.OnlinePK) {
+                this.transform.Find("Score" + i + "/Text").GetComponent<Text>().text = ((PKGameMode_OnlinePK)gameMode).gameLogic.totalScores[i - 1].ToString();
+            }
+        }
+        if (GlobalData.pkMatchType == PKMatchType.OnlinePK) {
+            Transform btnsTF = this.transform.Find("Btns");
+            for (int i = 0; i < btnsTF.childCount; i++) {
+                Transform tf = btnsTF.GetChild(i);
+                tf.gameObject.SetActive(tf.gameObject.name == "BtnBack");
+            }
         }
         }
         AudioMgr.ins.PlayWin();
         AudioMgr.ins.PlayWin();
     }
     }

+ 65 - 5
Assets/BowArrow/Scripts/View/PKGameView.cs

@@ -8,6 +8,7 @@ public class PKGameView : MonoBehaviour
 {
 {
     [SerializeField] Text[] scoreTexts;
     [SerializeField] Text[] scoreTexts;
     PKGameMode pKGameMode;
     PKGameMode pKGameMode;
+    PKGameMode_OnlinePK pKGameMode_OnlinePK;
     int currentPlayerIndex = -1;
     int currentPlayerIndex = -1;
     string[] numCNs = {"", "第一局", "第二局", "第三局", "第四局", "第五局", "第六局"};
     string[] numCNs = {"", "第一局", "第二局", "第三局", "第四局", "第五局", "第六局"};
     string[] numENs = {"", "1st leg", "2st leg", "3st leg", "4st leg", "5st leg", "6st leg"};
     string[] numENs = {"", "1st leg", "2st leg", "3st leg", "4st leg", "5st leg", "6st leg"};
@@ -17,19 +18,56 @@ public class PKGameView : MonoBehaviour
     void Start()
     void Start()
     {
     {
         ins = this;
         ins = this;
-        pKGameMode = (PKGameMode) GameMgr.ins.gameMode;
-        RenderPlayerInfo(1, PKGameMode.playerRoleIDs[0]);
-        RenderPlayerInfo(2, PKGameMode.playerRoleIDs[1]);
+        
+        InitPKGameMode();
+        RenderPlayerInfo();
     }
     }
 
 
-    void RenderPlayerInfo(int posNum, int playerID)
+    void InitPKGameMode() {
+        if (GlobalData.pkMatchType == PKMatchType.LocalPK) {
+            pKGameMode = (PKGameMode) GameMgr.ins.gameMode;
+        }
+        else if (GlobalData.pkMatchType == PKMatchType.OnlinePK) {
+            pKGameMode_OnlinePK = (PKGameMode_OnlinePK) GameMgr.ins.gameMode;
+        }
+    }
+
+    void RenderPlayerInfo() {
+        if (GlobalData.pkMatchType == PKMatchType.LocalPK) {
+            RenderPlayerInfo_LockPK(1, PKGameMode.playerRoleIDs[0]);
+            RenderPlayerInfo_LockPK(2, PKGameMode.playerRoleIDs[1]);
+        }
+        else if (GlobalData.pkMatchType == PKMatchType.OnlinePK) {
+            RenderPlayerInfo_OnlinePK(1, GlobalData.matchPlayerInfos[0].avatarID, GlobalData.matchPlayerInfos[0].nickname);
+            RenderPlayerInfo_OnlinePK(2, GlobalData.matchPlayerInfos[1].avatarID, GlobalData.matchPlayerInfos[1].nickname);
+        }
+    }
+
+    void RenderPlayerInfo_LockPK(int posNum, int roleID)
     {
     {
-        (Sprite avatar, string nickName) = RoleMgr.GetRoleInfo(playerID);
+        (Sprite avatar, string nickName) = RoleMgr.GetRoleInfo(roleID);
         this.transform.Find("TotalScore/Avatar" + posNum + "/Sprite").GetComponent<Image>().sprite = avatar;
         this.transform.Find("TotalScore/Avatar" + posNum + "/Sprite").GetComponent<Image>().sprite = avatar;
         this.transform.Find("TotalScore/Name" + posNum).GetComponent<Text>().text = nickName;
         this.transform.Find("TotalScore/Name" + posNum).GetComponent<Text>().text = nickName;
     }
     }
 
 
+    void RenderPlayerInfo_OnlinePK(int posNum, int roleID, string nickname)
+    {
+        (Sprite avatar, string _) = RoleMgr.GetRoleInfo(roleID);
+        this.transform.Find("TotalScore/Avatar" + posNum + "/Sprite").GetComponent<Image>().sprite = avatar;
+        this.transform.Find("TotalScore/Name" + posNum).GetComponent<Text>().text = nickname;
+    }
+
     void Update()
     void Update()
+    {
+        if (GlobalData.pkMatchType == PKMatchType.LocalPK) {
+            UpdateWhenLocalPK();
+        }
+        else if (GlobalData.pkMatchType == PKMatchType.OnlinePK) {
+            UpdateWhenOnlinePK();
+        }
+    }
+
+    void UpdateWhenLocalPK()
     {
     {
         scoreTexts[0].text = TextAutoLanguage.GetLanguage() == LanguageEnum.Chinese 
         scoreTexts[0].text = TextAutoLanguage.GetLanguage() == LanguageEnum.Chinese 
             ? numCNs[pKGameMode.round] : numENs[pKGameMode.round];
             ? numCNs[pKGameMode.round] : numENs[pKGameMode.round];
@@ -50,4 +88,26 @@ public class PKGameView : MonoBehaviour
             this.transform.Find("CurrentPlayer/Time").GetComponent<Text>().text = pKGameMode.GetTimeStr();
             this.transform.Find("CurrentPlayer/Time").GetComponent<Text>().text = pKGameMode.GetTimeStr();
         }
         }
     }
     }
+
+    void UpdateWhenOnlinePK()
+    {
+        scoreTexts[0].text = TextAutoLanguage.GetLanguage() == LanguageEnum.Chinese 
+            ? numCNs[pKGameMode_OnlinePK.gameLogic.round] : numENs[pKGameMode_OnlinePK.gameLogic.round];
+        scoreTexts[1].text = pKGameMode_OnlinePK.gameLogic.currentScores[0].ToString($"f{CommonConfig.ringsPrecision}");
+        scoreTexts[2].text = pKGameMode_OnlinePK.gameLogic.currentScores[1].ToString($"f{CommonConfig.ringsPrecision}");
+        scoreTexts[3].text = pKGameMode_OnlinePK.gameLogic.totalScores[0] + " : " + pKGameMode_OnlinePK.gameLogic.totalScores[1];
+            
+        if (currentPlayerIndex != pKGameMode_OnlinePK.gameLogic.currentPlayerIndex)
+        {
+            currentPlayerIndex = pKGameMode_OnlinePK.gameLogic.currentPlayerIndex;
+            (Sprite avatar, string nickName) = RoleMgr.GetRoleInfo(GlobalData.matchPlayerInfos[currentPlayerIndex].avatarID);
+            this.transform.Find("CurrentPlayer/Avatar").GetComponent<Image>().sprite = avatar;
+            this.transform.Find("CurrentPlayer/Name").GetComponent<Text>().text = GlobalData.matchPlayerInfos[currentPlayerIndex].nickname;
+        }
+        if (currentPlayerIndex == pKGameMode_OnlinePK.gameLogic.currentPlayerIndex) 
+        {
+            this.transform.Find("CurrentPlayer/Progress").GetComponent<Image>().fillAmount = pKGameMode_OnlinePK.gameLogic.singleShootReadyTime / pKGameMode_OnlinePK.gameLogic.singleShootReadyMaxTime;
+            this.transform.Find("CurrentPlayer/Time").GetComponent<Text>().text = TimeUtil.GetTimeStr(pKGameMode_OnlinePK.gameLogic.singleShootReadyTime);
+        }
+    }
 }
 }

+ 8 - 1
Assets/BowArrow/Scripts/View/PKMatchView.cs

@@ -19,8 +19,10 @@ public class PKMatchView : MonoBehaviour
     {
     {
         HomeMgr.CacheView(this);
         HomeMgr.CacheView(this);
 
 
-        (Sprite avatar, string nickname)  =  RoleMgr.GetRoleInfo(0);
+        (Sprite avatar, string nickname)  =  RoleMgr.GetRoleInfo(LoginMgr.myUserInfo.avatarID);
+        nickname = LoginMgr.myUserInfo.nickname;
         RenderPlayerInfo(1, avatar, nickname, true);
         RenderPlayerInfo(1, avatar, nickname, true);
+        SetBtnTabSelected(btnTabs[0]);
         RenderPlayerInfo(2, null, "", false);
         RenderPlayerInfo(2, null, "", false);
     }
     }
 
 
@@ -57,6 +59,11 @@ public class PKMatchView : MonoBehaviour
                 Image img = item.GetComponent<Image>();
                 Image img = item.GetComponent<Image>();
                 img.sprite = item == btn ? btnTabTextures[1] : btnTabTextures[0];
                 img.sprite = item == btn ? btnTabTextures[1] : btnTabTextures[0];
             }
             }
+            int index = Array.IndexOf(btnTabs, btnTabs);
+            HandleBtnTabSelectedLogic(index);
+        }
+        void HandleBtnTabSelectedLogic(int btnIndex) {
+            
         }
         }
     #endregion
     #endregion
 
 

+ 43 - 2
Assets/BowArrow/Scripts/View/PKMatchingView.cs

@@ -3,6 +3,7 @@ using System.Collections;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine;
 using UnityEngine.UI;
 using UnityEngine.UI;
+using UnityEngine.SceneManagement;
 
 
 public class PKMatchingView : MonoBehaviour
 public class PKMatchingView : MonoBehaviour
 {
 {
@@ -10,6 +11,8 @@ public class PKMatchingView : MonoBehaviour
 
 
     float waitingTime = 0;
     float waitingTime = 0;
 
 
+    SocketPlayer socketPlayer;
+
     void Awake()
     void Awake()
     {
     {
 
 
@@ -20,11 +23,41 @@ public class PKMatchingView : MonoBehaviour
         (Sprite avatar, string nickname)  =  RoleMgr.GetRoleInfo(0);
         (Sprite avatar, string nickname)  =  RoleMgr.GetRoleInfo(0);
         RenderPlayerInfo(1, avatar, nickname, true);
         RenderPlayerInfo(1, avatar, nickname, true);
         RenderPlayerInfo(2, null, "", false);
         RenderPlayerInfo(2, null, "", false);
+
+        socketPlayer = new GameObject("SocketPlayer").AddComponent<SocketPlayer>();
+        socketPlayer.onLoad_ = () => {
+            socketPlayer.UploadPlayerInfo();
+            socketPlayer.RandomMatchRoom();
+        };
+        socketPlayer.onMatchSuccess = () => {
+            int otherIndex = (GlobalData.playerIndexInRoom + 1) % 2;
+            MatchPlayerInfo info = GlobalData.matchPlayerInfos[otherIndex];
+            (Sprite avatar, string nickname)  =  RoleMgr.GetRoleInfo(info.avatarID);
+            nickname = LoginMgr.myUserInfo.nickname;
+            RenderPlayerInfo(2, avatar, nickname, true);
+            RenderTip("匹配成功,即将开始游戏!");
+            HideBtnBack();
+            PauseWaitingTime();
+            socketPlayer.AgreeStartGame();
+        };
+        socketPlayer.onAgreeStartGame = () => {
+            DontDestroyOnLoad(socketPlayer);
+            if (GlobalData.matchRoomType == 0) {
+                GameMgr.gameType = 9;
+                SceneManager.LoadScene("Game", LoadSceneMode.Single);
+            }
+        };
     }
     }
 
 
     void Update() {
     void Update() {
-        waitingTime += Time.deltaTime;
-        this.transform.Find("BoxRight/TimeBG").GetComponentInChildren<Text>().text = TimeUtil.GetTimeStr(waitingTime, false);
+        if (waitingTime >= 0) {
+            waitingTime += Time.deltaTime;
+            this.transform.Find("BoxRight/TimeBG").GetComponentInChildren<Text>().text = TimeUtil.GetTimeStr(waitingTime, false);
+        }
+    }
+
+    void PauseWaitingTime() {
+        waitingTime = -1;
     }
     }
 
 
     void RenderPlayerInfo(int playerID, Sprite avatar, string nickname, bool active) {
     void RenderPlayerInfo(int playerID, Sprite avatar, string nickname, bool active) {
@@ -41,6 +74,14 @@ public class PKMatchingView : MonoBehaviour
         img.GetComponent<Button>().enabled = typeIndex == 1;
         img.GetComponent<Button>().enabled = typeIndex == 1;
     }
     }
 
 
+    void RenderTip(string content) {
+        this.transform.Find("BoxRight/Tip").GetComponentInChildren<Text>().text = content;
+    }
+
+    void HideBtnBack() {
+        this.transform.Find("Back").gameObject.SetActive(false);
+    }
+
     public void Back() {
     public void Back() {
         AudioMgr.ins.PlayBtn();
         AudioMgr.ins.PlayBtn();
         Destroy(this.gameObject);
         Destroy(this.gameObject);

+ 257 - 0
Assets/DependAsset/JC/JCEngine.cs

@@ -0,0 +1,257 @@
+using System;
+using System.Collections.Generic;
+using BestHTTP.WebSocket;
+using Newtonsoft.Json;
+
+public class JCEngine {
+    public static string url;
+    public static Type entityClass;
+
+    public static void boot(string url, Type entityClass) {
+        JCEngine.url = url;
+        JCEngine.entityClass = entityClass;
+        new JCEngineCore.WebSocketServer(url, null);
+    }
+
+    public static void reBoot(JCEntity entity) {
+        new JCEngineCore.WebSocketServer(url, entity);
+    }
+}
+
+public class JCEntity {
+    public int id;
+    public JCEngineCore.Channel channel;
+    public bool isValid;
+    public bool loaded;
+    public Dictionary<string, object> components = new Dictionary<string, object>();
+
+    public virtual void onLoad() {}
+
+    public virtual void onReload() {}
+
+    public virtual void onDestroy() {}
+
+    public virtual void onMiss() {}
+
+    public bool call(string func, params object[] args) {
+        return call(func, args, null);
+    }
+
+    public bool call(string func, object[] args = null, Delegate callback = null) {
+        if (this.isValid) {
+            string uuid = "";
+            int type = Convert.ToInt32(JCEngineCore.DataType.FUNCTION);
+            if (func.IndexOf(".") > -1) {
+                type = Convert.ToInt32(JCEngineCore.DataType.METHOD);
+                uuid = JCEngineCore.CallbackHandler.addCallback(callback);
+            }
+            if (args == null) {
+                args = new object[]{};
+            }
+            JCEngineCore.Data data = new JCEngineCore.Data();
+            data.uuid = uuid;
+            data.type = type;
+            data.func = func;
+            data.args = args;
+            this.channel.writeAndFlush(JsonConvert.SerializeObject(data));
+            return true;
+        }
+        return false;
+    }
+}
+
+namespace JCEngineCore {
+    
+    public class Channel {
+        private WebSocket webSocket;
+
+        public Channel (WebSocket webSocket) {
+            this.webSocket = webSocket;
+        }
+
+        public void writeAndFlush(string text) {
+            this.webSocket.Send(text);
+        }
+
+        public void close() {
+            this.webSocket.Close();
+        }
+    }
+    class WebSocketServer {
+        private WebSocket webSocket;
+        private JCEntity tempEntity;
+    
+        public WebSocketServer(string url, JCEntity entity) {
+            this.webSocket = new WebSocket(new Uri(url));
+            this.webSocket.StartPingThread = true;
+            this.tempEntity = entity != null ? entity : JCEngine.entityClass.Assembly.CreateInstance(JCEngine.entityClass.FullName) as JCEntity;
+
+            this.webSocket.OnOpen += delegate(WebSocket webSocket) {
+                this.call("loadTempEntity");
+            };
+    
+            this.webSocket.OnClosed = delegate(WebSocket webSocket, UInt16 code, string message) {
+                this.destroyTempEntity();
+            };
+
+            this.webSocket.OnError = delegate(WebSocket webSocket, Exception ex) {
+                this.destroyTempEntity();
+            };
+    
+            this.webSocket.OnMessage = delegate(WebSocket webSocket, string message) {
+                this.invoke(JsonConvert.DeserializeObject<Data>(message));            
+            };
+
+            this.webSocket.Open();
+        }
+    
+        private void call(string func, object[] args = null) {
+            if (args == null) {
+                args = new object[]{};
+            }
+            Data data = new Data();
+            data.uuid = "";
+            data.type = Convert.ToInt32(DataType.EVENT);
+            data.func = func;
+            data.args = args;
+            this.webSocket.Send(JsonConvert.SerializeObject(data));
+        }
+    
+        private void invoke(Data data) {
+            DataType dataType = (DataType) data.type;
+            if (dataType == DataType.EVENT) {
+                System.Reflection.MethodInfo method = this.GetType().GetMethod(data.func);
+                Utility.formatArgsType(data.args, method.GetParameters());
+                method.Invoke(this, data.args);
+                return;
+            }
+            if (dataType == DataType.FUNCTION) {
+                if (this.tempEntity.isValid) {
+                    string func = data.func;
+                    object context = this.tempEntity;;
+                    int pointIndex = func.LastIndexOf(".");
+                    if (pointIndex > -1) {
+                        context = null;
+                        string key = func.Substring(0, pointIndex);
+                        object matchContext;
+                        this.tempEntity.components.TryGetValue(key, out matchContext);
+                        if (matchContext != null) {
+                            string[] arr = func.Split(new char[]{'.'});
+                            func = arr[arr.Length - 1];
+                            context = matchContext;
+                        }
+                    }
+                    if (context != null) {
+                        System.Reflection.MethodInfo method = context.GetType().GetMethod(func);
+                        Utility.formatArgsType(data.args, method.GetParameters());
+                        method.Invoke(context, data.args);
+                    }
+                }
+                return;
+            }
+            if (dataType == DataType.METHOD) {
+                CallbackHandler.handleCallback(data);
+            }
+        }
+    
+        public void loadTempEntity(int id) {
+            this.tempEntity.id = id;
+            this.tempEntity.channel = new Channel(this.webSocket);
+            this.tempEntity.isValid = true;
+            try {
+                if (this.tempEntity.loaded) {
+                    this.tempEntity.onReload();
+                } else {
+                    this.tempEntity.onLoad();
+                }
+            } catch (Exception) {}
+            this.tempEntity.loaded = true;
+        }
+    
+        public void destroyTempEntity() {
+            if (this.tempEntity.isValid) {
+                this.tempEntity.isValid = false;
+                this.tempEntity.onDestroy();            
+            } else {
+                this.tempEntity.onMiss();
+            }
+        }
+    }
+
+    class CallbackHandler {
+        private static int nextID = 0;
+        private static Dictionary<string, CallbackInfo> mapper = new Dictionary<string, CallbackInfo>();
+    
+        private static string uuid() {
+            nextID++;
+            return nextID.ToString();
+        }
+    
+        public static string addCallback(Delegate callback) {
+            string uuid = CallbackHandler.uuid();
+            if (callback != null) {
+                CallbackInfo callbackInfo = new CallbackInfo();
+                callbackInfo.callback = callback;
+                callbackInfo.deadTime = Utility.GetTimestamp() + 10 * 1000;
+                mapper.Add(uuid, callbackInfo);
+            }
+            return uuid;
+        }
+    
+        public static void handleCallback(Data data) {
+            if (mapper.Count > 10) {
+                long now = Utility.GetTimestamp();
+                LinkedList<string> outKeys = new LinkedList<string>();
+                foreach (var item in mapper) {
+                    if (now >= item.Value.deadTime) {
+                        outKeys.AddLast(item.Key);
+                    }
+                }
+                foreach (var item in outKeys) {
+                    mapper.Remove(item);
+                }
+            }
+            CallbackInfo callbackInfo;
+            mapper.TryGetValue(data.uuid, out callbackInfo);
+            if (callbackInfo != null) {
+                mapper.Remove(data.uuid);
+                object target = callbackInfo.callback.Target;
+                System.Reflection.MethodInfo method = callbackInfo.callback.Method;
+                Utility.formatArgsType(data.args, method.GetParameters());
+                method.Invoke(target, data.args);
+            }
+        }
+    }
+
+    class Utility {
+        public static long GetTimestamp() {
+            TimeSpan ts = DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1);
+            return (long)ts.TotalMilliseconds;
+        }
+        public static void formatArgsType(object[] args, System.Reflection.ParameterInfo[] parameters) {
+            int i = 0;
+            foreach (var param in parameters) {
+                args[i] = Convert.ChangeType(args[i], param.ParameterType);
+                i++;
+            }
+        }
+    }
+
+    class CallbackInfo {
+        public Delegate callback;
+        public long deadTime;
+    }
+    
+    class Data {
+        public string uuid;
+        public int type;
+        public string func;
+        public object[] args;
+    }
+    
+    enum DataType {
+        EVENT,
+        FUNCTION,
+        METHOD
+    }
+}

+ 11 - 0
Assets/DependAsset/JC/JCEngine.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0c440ae5c8bee74448b89e4b93f2726d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 52 - 49
Assets/DependAsset/JC/JCSocketIO.cs

@@ -1,56 +1,48 @@
 using System;
 using System;
 using UnityEngine;
 using UnityEngine;
-using BestHTTP.SocketIO;
+using BestHTTP.WebSocket;
 using Newtonsoft.Json;
 using Newtonsoft.Json;
 
 
 namespace JC.SocketIO {
 namespace JC.SocketIO {
 
 
     public class SocketIOClient : MonoBehaviour {
     public class SocketIOClient : MonoBehaviour {
-        private SocketManager _manager;
-        private Socket _socket;
+        private WebSocket _ws;
         private string _uri;
         private string _uri;
 
 
         public virtual void OnDestroy() {
         public virtual void OnDestroy() {
-            if (_manager != null) {
-                _manager.Close();
+            if (_ws != null) {
+                _ws.Close();
+                _ws = null;
             }
             }
         }
         }
 
 
         public void connectServer(string uri) {
         public void connectServer(string uri) {
-            _uri = uri;
-            _manager = new SocketManager(new System.Uri(_uri));
-            _manager.Options.AutoConnect = true; //自动打开
-            _manager.Options.Reconnection = true; //自动重连
-            _socket = _manager.Socket;
-            _socket.On(SocketIOEventTypes.Error, delegate(Socket socket, Packet packet, object[] args) {
-                if (!isValid) {
-                    try {
-                        onMiss();
-                    } catch (Exception e) { Debug.LogError(e.Message); }
-                }
-            });
-            _socket.On(SocketIOEventTypes.Disconnect, delegate(Socket socket, Packet packet, object[] args) {
-                if (isValid) {
-                    isValid = false;
-                    try {
-                        onDestroy();
-                    } catch (Exception e) { Debug.LogError(e.Message); }
-                }
-            });
-            _socket.On("call", delegate(Socket socket, Packet packet, object[] args) {
-                string str = packet.Payload;
-                int si = str.IndexOf("{");
-                int ei = str.LastIndexOf("]");
-                str = str.Substring(si, ei - si);
-                invoke(JsonConvert.DeserializeObject<DataPack>(str));
-            });
+            this._uri = uri;
+            this._ws = new WebSocket(new Uri(this._uri));
+            this._ws.StartPingThread = true;
+            this._ws.OnOpen += delegate(WebSocket webSocket) {
+                loadEntity();
+            };
+            this._ws.OnClosed = delegate(WebSocket webSocket, UInt16 code, string message) {
+                destroyEntity();
+            };
+            this._ws.OnError = delegate(WebSocket webSocket, Exception ex) {
+                destroyEntity();
+            };
+            this._ws.OnMessage = delegate(WebSocket webSocket, string message) {
+                this.invoke(JsonConvert.DeserializeObject<DataPack>(message));            
+            };
+            this._ws.Open();
         }
         }
 
 
         public void reconnectServer() {
         public void reconnectServer() {
-            if (_manager != null) {
-                _manager.Close();
+            if (_ws != null) {
+                _ws.Close();
+                _ws = null;
+            }
+            if (_uri != null) {
+                connectServer(_uri);
             }
             }
-            connectServer(_uri);
         }
         }
 
 
         [NonSerialized] public bool isValid;
         [NonSerialized] public bool isValid;
@@ -70,29 +62,40 @@ namespace JC.SocketIO {
             dataPack.type = 1;
             dataPack.type = 1;
             dataPack.func = func;
             dataPack.func = func;
             dataPack.args = Utility.FormatArgs(args);
             dataPack.args = Utility.FormatArgs(args);
-            _socket.Emit("call", JsonConvert.SerializeObject(dataPack));
+            _ws.Send(JsonConvert.SerializeObject(dataPack));
         }
         }
 
 
         private void invoke(DataPack dataPack) {
         private void invoke(DataPack dataPack) {
-            if (dataPack.type == 0) {
-                if (dataPack.func == "onLoad") {
-                    isValid = true;
-                    try {
-                        if (loaded) {
-                            onReload();
-                        } else {
-                            onLoad();
-                        }
-                    } catch (Exception e) { Debug.LogError(e.Message); }
-                    loaded = true;
-                }
-            } else if (dataPack.type == 1) {
+            if (dataPack.type == 1) {
                 System.Reflection.MethodInfo method = this.GetType().GetMethod(dataPack.func);
                 System.Reflection.MethodInfo method = this.GetType().GetMethod(dataPack.func);
                 Utility.FormatArgsType(dataPack.args, method.GetParameters());
                 Utility.FormatArgsType(dataPack.args, method.GetParameters());
                 method.Invoke(this, dataPack.args);
                 method.Invoke(this, dataPack.args);
             }
             }
         }
         }
 
 
+         public void loadEntity() {
+            this.isValid = true;
+            try {
+                if (this.loaded) {
+                    this.onReload();
+                } else {
+                    this.onLoad();
+                }
+            } catch (Exception e) { Debug.LogError(e.Message); }
+            this.loaded = true;
+        }
+
+        private void destroyEntity() {
+            try {
+                if (this.isValid) {
+                    this.isValid = false;
+                    this.onDestroy();            
+                } else {
+                    this.onMiss();
+                }
+            } catch (Exception e) { Debug.LogError(e.Message); }
+        }
+
         class DataPack {
         class DataPack {
             public int type;
             public int type;
             public string func;
             public string func;