瀏覽代碼

双设备

lvjincheng 2 年之前
父節點
當前提交
dedb618bb3
共有 44 個文件被更改,包括 3021 次插入317 次删除
  1. 7 2
      Assets/BowArrow/Resources/Prefabs/Effects/HitTargetNumber.prefab
  2. 247 0
      Assets/BowArrow/Resources/Prefabs/Effects/HitTargetNumber0.prefab
  3. 7 0
      Assets/BowArrow/Resources/Prefabs/Effects/HitTargetNumber0.prefab.meta
  4. 247 0
      Assets/BowArrow/Resources/Prefabs/Effects/HitTargetNumber1.prefab
  5. 7 0
      Assets/BowArrow/Resources/Prefabs/Effects/HitTargetNumber1.prefab.meta
  6. 2 2
      Assets/BowArrow/Resources/Prefabs/Views/PKGameSettleView.prefab
  7. 642 266
      Assets/BowArrow/Scenes/Game.unity
  8. 20 20
      Assets/BowArrow/Scripts/Bluetooth/BluetoothAim.cs
  9. 1 1
      Assets/BowArrow/Scripts/Expand/SB_EventSystem.cs
  10. 2 2
      Assets/BowArrow/Scripts/Expand/SimulateMouseController.cs
  11. 4 4
      Assets/BowArrow/Scripts/Game/PointSignLastHit.cs
  12. 2 1
      Assets/BowArrow/Scripts/Game/TargetView.cs
  13. 8 0
      Assets/SmartBowGame.meta
  14. 195 0
      Assets/SmartBowGame/AimCrossHair.cs
  15. 11 0
      Assets/SmartBowGame/AimCrossHair.cs.meta
  16. 426 0
      Assets/SmartBowGame/ArrowNew.cs
  17. 11 0
      Assets/SmartBowGame/ArrowNew.cs.meta
  18. 147 0
      Assets/SmartBowGame/BLEView.cs
  19. 11 0
      Assets/SmartBowGame/BLEView.cs.meta
  20. 47 0
      Assets/SmartBowGame/DistanceSelectView.cs
  21. 11 0
      Assets/SmartBowGame/DistanceSelectView.cs.meta
  22. 58 0
      Assets/SmartBowGame/GameCanvas.cs
  23. 11 0
      Assets/SmartBowGame/GameCanvas.cs.meta
  24. 90 0
      Assets/SmartBowGame/GameController.cs
  25. 11 0
      Assets/SmartBowGame/GameController.cs.meta
  26. 32 0
      Assets/SmartBowGame/GameEntry.cs
  27. 11 0
      Assets/SmartBowGame/GameEntry.cs.meta
  28. 47 0
      Assets/SmartBowGame/HitTargetNumberNew.cs
  29. 11 0
      Assets/SmartBowGame/HitTargetNumberNew.cs.meta
  30. 54 0
      Assets/SmartBowGame/PKGameSettleViewNew.cs
  31. 11 0
      Assets/SmartBowGame/PKGameSettleViewNew.cs.meta
  32. 60 0
      Assets/SmartBowGame/TargetBodyNew.cs
  33. 11 0
      Assets/SmartBowGame/TargetBodyNew.cs.meta
  34. 8 0
      Assets/SmartBowSDK.meta
  35. 454 0
      Assets/SmartBowSDK/BleWinHelper.cs
  36. 11 0
      Assets/SmartBowSDK/BleWinHelper.cs.meta
  37. 二進制
      Assets/SmartBowSDK/BleWinrtDll.dll
  38. 27 0
      Assets/SmartBowSDK/BleWinrtDll.dll.meta
  39. 二進制
      Assets/SmartBowSDK/SmartBowSDK.dll
  40. 33 0
      Assets/SmartBowSDK/SmartBowSDK.dll.meta
  41. 4 0
      Assets/SmartBowSDK/link.xml
  42. 7 0
      Assets/SmartBowSDK/link.xml.meta
  43. 10 5
      Assets/ThirdAssets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset
  44. 5 14
      ProjectSettings/EditorBuildSettings.asset

+ 7 - 2
Assets/BowArrow/Resources/Prefabs/Effects/HitTargetNumber.prefab

@@ -28,6 +28,7 @@ RectTransform:
   m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
   m_LocalPosition: {x: 0, y: 0, z: 0}
   m_LocalScale: {x: 2, y: 2, z: 1}
+  m_ConstrainProportionsScale: 0
   m_Children: []
   m_Father: {fileID: 3953484096697592400}
   m_RootOrder: 1
@@ -106,6 +107,7 @@ RectTransform:
   m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
   m_LocalPosition: {x: 0, y: 0, z: 0}
   m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
   m_Children:
   - {fileID: 1537881960295453758}
   - {fileID: 3953484096588243019}
@@ -158,6 +160,7 @@ RectTransform:
   m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
   m_LocalPosition: {x: 0, y: 0, z: 0}
   m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
   m_Children: []
   m_Father: {fileID: 3953484096697592400}
   m_RootOrder: 0
@@ -207,7 +210,7 @@ MonoBehaviour:
   m_PixelsPerUnitMultiplier: 1
 --- !u!95 &5679497542507818410
 Animator:
-  serializedVersion: 3
+  serializedVersion: 5
   m_ObjectHideFlags: 0
   m_CorrespondingSourceObject: {fileID: 0}
   m_PrefabInstance: {fileID: 0}
@@ -220,7 +223,9 @@ Animator:
   m_UpdateMode: 0
   m_ApplyRootMotion: 0
   m_LinearVelocityBlending: 0
+  m_StabilizeFeet: 0
   m_WarningMessage: 
   m_HasTransformHierarchy: 1
   m_AllowConstantClipSamplingOptimization: 1
-  m_KeepAnimatorControllerStateOnDisable: 0
+  m_KeepAnimatorStateOnDisable: 0
+  m_WriteDefaultValuesOnDisable: 0

+ 247 - 0
Assets/BowArrow/Resources/Prefabs/Effects/HitTargetNumber0.prefab

@@ -0,0 +1,247 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &3953484096588243018
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 3953484096588243019}
+  - component: {fileID: 3953484096588243021}
+  - component: {fileID: 4143598657192338911}
+  - component: {fileID: 4369249835293911280}
+  m_Layer: 5
+  m_Name: Text
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &3953484096588243019
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3953484096588243018}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 2, y: 2, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 3953484096697592400}
+  m_RootOrder: 1
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 5, y: -7}
+  m_SizeDelta: {x: 600, y: 300}
+  m_Pivot: {x: 0.5, y: 0.488}
+--- !u!222 &3953484096588243021
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3953484096588243018}
+  m_CullTransparentMesh: 1
+--- !u!114 &4143598657192338911
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3953484096588243018}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_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: 40
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 0
+    m_MaxSize: 45
+    m_Alignment: 4
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: 
+--- !u!114 &4369249835293911280
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3953484096588243018}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: e19747de3f5aca642ab2be37e372fb86, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_EffectColor: {r: 1, g: 0.390566, b: 0.390566, a: 0.5}
+  m_EffectDistance: {x: 2, y: -2}
+  m_UseGraphicAlpha: 1
+--- !u!1 &3953484096697592415
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 3953484096697592400}
+  - component: {fileID: 6828244992260652330}
+  m_Layer: 5
+  m_Name: HitTargetNumber0
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &3953484096697592400
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3953484096697592415}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 1537881960295453758}
+  - {fileID: 3953484096588243019}
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 100, y: 100}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &6828244992260652330
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3953484096697592415}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 633cdb1e56b510141927ba75c817aeea, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+--- !u!1 &5547216466910056294
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1537881960295453758}
+  - component: {fileID: 4346446659102155494}
+  - component: {fileID: 1635824888092130653}
+  - component: {fileID: 5679497542507818410}
+  m_Layer: 5
+  m_Name: Line
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 0
+--- !u!224 &1537881960295453758
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5547216466910056294}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 3953484096697592400}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 544.5, y: 153.186}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &4346446659102155494
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5547216466910056294}
+  m_CullTransparentMesh: 1
+--- !u!114 &1635824888092130653
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5547216466910056294}
+  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: 0.14528298, b: 0.14528298, 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: e3c2a35f17311044695fdd3fc50838bb, type: 3}
+  m_Type: 0
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!95 &5679497542507818410
+Animator:
+  serializedVersion: 5
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5547216466910056294}
+  m_Enabled: 1
+  m_Avatar: {fileID: 0}
+  m_Controller: {fileID: 9100000, guid: b2a68c7ff654b7648afdc164385b846d, type: 2}
+  m_CullingMode: 0
+  m_UpdateMode: 0
+  m_ApplyRootMotion: 0
+  m_LinearVelocityBlending: 0
+  m_StabilizeFeet: 0
+  m_WarningMessage: 
+  m_HasTransformHierarchy: 1
+  m_AllowConstantClipSamplingOptimization: 1
+  m_KeepAnimatorStateOnDisable: 0
+  m_WriteDefaultValuesOnDisable: 0

+ 7 - 0
Assets/BowArrow/Resources/Prefabs/Effects/HitTargetNumber0.prefab.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: d43f9aca0a46bc54f99343987d045f8b
+PrefabImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 247 - 0
Assets/BowArrow/Resources/Prefabs/Effects/HitTargetNumber1.prefab

@@ -0,0 +1,247 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &3953484096588243018
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 3953484096588243019}
+  - component: {fileID: 3953484096588243021}
+  - component: {fileID: 4143598657192338911}
+  - component: {fileID: 4369249835293911280}
+  m_Layer: 5
+  m_Name: Text
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &3953484096588243019
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3953484096588243018}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 2, y: 2, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 3953484096697592400}
+  m_RootOrder: 1
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 5, y: -7}
+  m_SizeDelta: {x: 600, y: 300}
+  m_Pivot: {x: 0.5, y: 0.488}
+--- !u!222 &3953484096588243021
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3953484096588243018}
+  m_CullTransparentMesh: 1
+--- !u!114 &4143598657192338911
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3953484096588243018}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_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: 40
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 0
+    m_MaxSize: 45
+    m_Alignment: 4
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: 
+--- !u!114 &4369249835293911280
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3953484096588243018}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: e19747de3f5aca642ab2be37e372fb86, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_EffectColor: {r: 0.3339622, g: 0.57212096, b: 1, a: 0.5}
+  m_EffectDistance: {x: 2, y: -2}
+  m_UseGraphicAlpha: 1
+--- !u!1 &3953484096697592415
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 3953484096697592400}
+  - component: {fileID: 6828244992260652330}
+  m_Layer: 5
+  m_Name: HitTargetNumber1
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &3953484096697592400
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3953484096697592415}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 1537881960295453758}
+  - {fileID: 3953484096588243019}
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 100, y: 100}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &6828244992260652330
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3953484096697592415}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 633cdb1e56b510141927ba75c817aeea, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+--- !u!1 &5547216466910056294
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1537881960295453758}
+  - component: {fileID: 4346446659102155494}
+  - component: {fileID: 1635824888092130653}
+  - component: {fileID: 5679497542507818410}
+  m_Layer: 5
+  m_Name: Line
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 0
+--- !u!224 &1537881960295453758
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5547216466910056294}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 3953484096697592400}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 544.5, y: 153.186}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &4346446659102155494
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5547216466910056294}
+  m_CullTransparentMesh: 1
+--- !u!114 &1635824888092130653
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5547216466910056294}
+  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: e3c2a35f17311044695fdd3fc50838bb, type: 3}
+  m_Type: 0
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!95 &5679497542507818410
+Animator:
+  serializedVersion: 5
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 5547216466910056294}
+  m_Enabled: 1
+  m_Avatar: {fileID: 0}
+  m_Controller: {fileID: 9100000, guid: b2a68c7ff654b7648afdc164385b846d, type: 2}
+  m_CullingMode: 0
+  m_UpdateMode: 0
+  m_ApplyRootMotion: 0
+  m_LinearVelocityBlending: 0
+  m_StabilizeFeet: 0
+  m_WarningMessage: 
+  m_HasTransformHierarchy: 1
+  m_AllowConstantClipSamplingOptimization: 1
+  m_KeepAnimatorStateOnDisable: 0
+  m_WriteDefaultValuesOnDisable: 0

+ 7 - 0
Assets/BowArrow/Resources/Prefabs/Effects/HitTargetNumber1.prefab.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: ce8de09b276ad8f498a07f2783cb2a95
+PrefabImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

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

@@ -327,7 +327,7 @@ RectTransform:
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_AnchorMin: {x: 0, y: 0}
   m_AnchorMax: {x: 0, y: 0}
-  m_AnchoredPosition: {x: 36, y: 0}
+  m_AnchoredPosition: {x: 0, y: 0}
   m_SizeDelta: {x: 0, y: 0}
   m_Pivot: {x: 0.5, y: 0.5}
 --- !u!222 &4192900400895089148
@@ -455,7 +455,7 @@ RectTransform:
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_AnchorMin: {x: 0, y: 0}
   m_AnchorMax: {x: 0, y: 0}
-  m_AnchoredPosition: {x: 116, y: 0}
+  m_AnchoredPosition: {x: 0, y: 0}
   m_SizeDelta: {x: 0, y: 0}
   m_Pivot: {x: 0.5, y: 0.5}
 --- !u!222 &1871444126788684677

File diff suppressed because it is too large
+ 642 - 266
Assets/BowArrow/Scenes/Game.unity


+ 20 - 20
Assets/BowArrow/Scripts/Bluetooth/BluetoothAim.cs

@@ -124,26 +124,26 @@ public class BluetoothAim : MonoBehaviour
             DoConnect();
         }
         if (doConnect) Connect();
-        if (CommonConfig.StandaloneMode)
-        {
-            if (!userDoConnect && status == BluetoothStatusEnum.Connect)
-            {
-                if (notUserDoConnectTime == 0)
-                {
-                    DoConnect();
-                    notUserDoConnectTime = 0.1f;
-                }
-                else
-                {
-                    notUserDoConnectTime += Time.deltaTime;
-                    if (notUserDoConnectTime > 2.5f)
-                    {
-                        DoConnect();
-                        notUserDoConnectTime = 0.1f;
-                    }
-                }
-            }
-        }
+        //if (CommonConfig.StandaloneMode)
+        //{
+        //    if (!userDoConnect && status == BluetoothStatusEnum.Connect)
+        //    {
+        //        if (notUserDoConnectTime == 0)
+        //        {
+        //            DoConnect();
+        //            notUserDoConnectTime = 0.1f;
+        //        }
+        //        else
+        //        {
+        //            notUserDoConnectTime += Time.deltaTime;
+        //            if (notUserDoConnectTime > 2.5f)
+        //            {
+        //                DoConnect();
+        //                notUserDoConnectTime = 0.1f;
+        //            }
+        //        }
+        //    }
+        //}
     }
 
     void SetStatus(BluetoothStatusEnum statusValue)

+ 1 - 1
Assets/BowArrow/Scripts/Expand/SB_EventSystem.cs

@@ -26,7 +26,7 @@ public class SB_EventSystem : MonoBehaviour
 
     void Start() {
         InitListenerForMouseHoverHightColor();
-        if (CommonConfig.StandaloneMode) gameObject.AddComponent<KeyBoardSelector>();
+        //if (CommonConfig.StandaloneMode) gameObject.AddComponent<KeyBoardSelector>();
     }
 
     void Update() {

+ 2 - 2
Assets/BowArrow/Scripts/Expand/SimulateMouseController.cs

@@ -29,13 +29,13 @@ public class SimulateMouseController
     public void AddOpenLocker(object locker) {
         openLockerSet.Add(locker);
         CheckAndOpenOrClose();
-        // Debug.Log("AddOpenLock-" + locker);
+        Debug.Log("AddOpenLock-" + locker);
     }
 
     public void RemoveOpenLocker(object locker) {
         openLockerSet.Remove(locker);
         CheckAndOpenOrClose();
-        // Debug.Log("RemoveOpenLock-" + locker);
+        Debug.Log("RemoveOpenLock-" + locker);
     }
 
     //蓝牙是否处于连接状态

+ 4 - 4
Assets/BowArrow/Scripts/Game/PointSignLastHit.cs

@@ -16,10 +16,10 @@ public class PointSignLastHit : MonoBehaviour
     {
         ins = this;
         gameObject.layer = LayerMask.NameToLayer("Test");
-        Hide();
-        GameEventCenter.ins.onBowArrowShootOut += (a, b) => {
-            Hide();
-        };
+        //Hide();
+        //GameEventCenter.ins.onBowArrowShootOut += (a, b) => {
+        //    Hide();
+        //};
     }
 
     void OnDestroy()

+ 2 - 1
Assets/BowArrow/Scripts/Game/TargetView.cs

@@ -58,7 +58,8 @@ public class TargetView : MonoBehaviour
     public static TargetView ins {
         get {
             if (_ins == null) {
-                _ins = GameObject.Find("Canvas/GameAssistUI/TargetView").GetComponent<TargetView>();
+                var tv = GameObject.Find("Canvas/GameAssistUI/TargetView");
+                if (tv) _ins = tv.GetComponent<TargetView>();
             }
             return _ins;
         }

+ 8 - 0
Assets/SmartBowGame.meta

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

+ 195 - 0
Assets/SmartBowGame/AimCrossHair.cs

@@ -0,0 +1,195 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+
+public class AimCrossHair : MonoBehaviour
+{
+    public Camera mainCamera;
+    [NonSerialized] public bool outboundLeft;
+    [NonSerialized] public bool outboundRight;
+    [NonSerialized] public bool outboundUp;
+    [NonSerialized] public bool outboundDown;
+
+    public static AimCrossHair Instance;
+
+    void Start()
+    {
+        Instance = this;
+
+        int currentShootLevel = UserSettings.ins.shootLevel;
+        shootBackTime = new int[] { 0, 2, 5 }[currentShootLevel];
+        shootOffsetAngleScale = new float[] { 0, 10f, 10f }[currentShootLevel];
+    }
+
+    void OnDestroy()
+    {
+        if (Instance == this) Instance = null;
+    }
+
+    void Update()
+    {
+        if (GetPlayerIndex() == 0)
+        {
+            UpdatePositionByModuleRotation(mouseTest.Update(0));
+            if (Input.GetKeyDown(KeyCode.Q)) Shoot();
+        }
+        else if (GetPlayerIndex() == 1)
+        {
+            UpdatePositionByModuleRotation(mouseTest.Update(1));
+            if (Input.GetKeyDown(KeyCode.E)) Shoot();
+        }
+        if (GameController.ins.gameStart && !GameController.ins.gameOver)
+        {
+            transform.localScale = Vector3.one;
+        }
+        else transform.localScale = Vector3.zero;
+    }
+
+    int GetPlayerIndex()
+    {
+        return Array.IndexOf(GameController.ins.aimCrossHairs, this);
+    }
+
+    MouseTest mouseTest = new MouseTest();
+    class MouseTest
+    {
+        Quaternion quat = Quaternion.identity;
+        float moveSensitivity = 30;
+        public Quaternion Update(int type)
+        {
+            if (type == 0)
+            {
+                if (Input.GetKey(KeyCode.A))
+                {
+                    quat = Quaternion.AngleAxis(-moveSensitivity * Time.deltaTime, Vector3.up) * quat;
+                }
+                else if (Input.GetKey(KeyCode.D))
+                {
+                    quat = Quaternion.AngleAxis(moveSensitivity * Time.deltaTime, Vector3.up) * quat;
+                }
+                else if (Input.GetKey(KeyCode.W))
+                {
+                    quat = Quaternion.AngleAxis(-moveSensitivity * Time.deltaTime, Vector3.right) * quat;
+                }
+                else if (Input.GetKey(KeyCode.S))
+                {
+                    quat = Quaternion.AngleAxis(moveSensitivity * Time.deltaTime, Vector3.right) * quat;
+                }
+            }
+            else if (type == 1)
+            {
+                if (Input.GetKey(KeyCode.LeftArrow))
+                {
+                    quat = Quaternion.AngleAxis(-moveSensitivity * Time.deltaTime, Vector3.up) * quat;
+                }
+                else if (Input.GetKey(KeyCode.RightArrow))
+                {
+                    quat = Quaternion.AngleAxis(moveSensitivity * Time.deltaTime, Vector3.up) * quat;
+                }
+                else if (Input.GetKey(KeyCode.UpArrow))
+                {
+                    quat = Quaternion.AngleAxis(-moveSensitivity * Time.deltaTime, Vector3.right) * quat;
+                }
+                else if (Input.GetKey(KeyCode.DownArrow))
+                {
+                    quat = Quaternion.AngleAxis(moveSensitivity * Time.deltaTime, Vector3.right) * quat;
+                }
+            }
+            return quat;
+        }
+    }
+
+    Quaternion currentRotation = Quaternion.identity;
+    public void UpdatePositionByModuleRotation(Quaternion moduleRotation)
+    {
+        // 限制模块欧拉角范围
+        Vector3 moduleAngles = moduleRotation.eulerAngles;
+        moduleAngles.x = Mathf.Clamp(moduleAngles.x > 180 ? moduleAngles.x - 360 : moduleAngles.x, -80, 80);
+        moduleAngles.y = Mathf.Clamp(moduleAngles.y > 180 ? moduleAngles.y - 360 : moduleAngles.y, -80, 80);
+        moduleRotation = Quaternion.Euler(moduleAngles);
+        currentRotation = moduleRotation;
+
+        // 计算准心的世界旋转
+        Quaternion rotation = mainCamera.transform.rotation * moduleRotation;
+
+        // 计算准心的世界方向
+        Vector3 direction = rotation * Vector3.forward;
+
+        // 计算准心的世界坐标
+        Vector3 position = mainCamera.transform.position + direction;
+
+        // 转为屏幕坐标
+        Vector3 screenPos = mainCamera.WorldToScreenPoint(position);
+
+        // 标记是否超出屏幕边界
+        outboundLeft = screenPos.x < 0;
+        outboundRight = screenPos.x > Screen.width;
+        outboundUp = screenPos.y > Screen.height;
+        outboundDown = screenPos.y < 0;
+
+        // 根据需要的范围进行限制
+        screenPos.x = Mathf.Clamp(screenPos.x, 0, Screen.width);
+        screenPos.y = Mathf.Clamp(screenPos.y, 0, Screen.height);
+
+        // 设置准心的位置
+        transform.position = screenPos;
+    }
+
+    //射箭姿态记录索引倒退数,根据射击难度制造误差
+    [NonSerialized] public int shootBackTime = 0;
+    [NonSerialized] public float shootOffsetAngleScale = 0;
+    //过去几帧的镜头值记录
+    Quaternion[] cameraRotations = new Quaternion[6];
+    int cameraRotationHasRecordCount = 0;
+    public void Shoot(float shootSpeedNow = 60f)
+    {
+        if (!GameController.ins.gameStart || GameController.ins.gameOver) return;
+        #region 
+        Quaternion absolute_rotation = currentRotation;
+        Quaternion final_rotation = currentRotation;
+        if (cameraRotationHasRecordCount >= cameraRotations.Length)
+        {
+            absolute_rotation = cameraRotations[5];
+            final_rotation = cameraRotations[5 - this.shootBackTime];
+        }
+        #endregion
+
+        Quaternion oldCameraRotation = currentRotation;
+        currentRotation = absolute_rotation;
+        RaycastHit absoluteRay = GetRaycastHit();
+        currentRotation = oldCameraRotation;
+
+        Vector3 shootOutPosition = mainCamera.transform.position + currentRotation * Vector3.forward * 1f;
+        Vector3 arrowEuler = absolute_rotation.eulerAngles;
+        arrowEuler.z = 0; //绝对角可能是从原始九轴记录数组里取出来的,它的z可能不是0
+        GameObject arrowCopy = Instantiate(GameController.ins.arrowPrefab, shootOutPosition, Quaternion.Euler(arrowEuler));
+
+        ArrowNew arrowComp = arrowCopy.AddComponent<ArrowNew>();
+        arrowComp.playerIndex = GetPlayerIndex();
+        arrowComp.shootOffsetAngleScale = shootOffsetAngleScale;
+        arrowComp.shootOutPosition = shootOutPosition;
+        arrowComp.absoluteRay = absoluteRay;
+        arrowComp.offsetAngle = GameDebug.ins ?
+            GameDebug.ins.GetOffsetAngle() :
+            Quaternion.Angle(absolute_rotation, final_rotation);
+        arrowComp.finalAngleAfterOffset = final_rotation.eulerAngles;
+
+        Arrow.speed = GameMgr.RealSizeToGameSize(shootSpeedNow);
+
+        //GameEventCenter.ins.onBowArrowShootOut?.Invoke(this, arrowComp);
+
+        AudioMgr.ins.PlayShoot(AudioMgr.GetAudioSource(arrowCopy));
+        //if (AimHandler.ins) AimHandler.ins.Ban9AxisCalculate(true);
+    }
+
+    public RaycastHit GetRaycastHit()
+    {
+        float maxDistance = 100;
+        int layerMask = 1 << 8; //TargetLayerMask
+        RaycastHit raycastHit;
+        Ray ray = new Ray(mainCamera.transform.position, currentRotation * Vector3.forward);
+        Physics.Raycast(ray.origin, ray.direction, out raycastHit, maxDistance, layerMask);
+        return raycastHit;
+    }
+}

+ 11 - 0
Assets/SmartBowGame/AimCrossHair.cs.meta

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

+ 426 - 0
Assets/SmartBowGame/ArrowNew.cs

@@ -0,0 +1,426 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using DG.Tweening;
+
+/* 箭对象 */
+public class ArrowNew : MonoBehaviour
+{
+    //飞行时间统计
+    [NonSerialized] public float flyTime = 0;
+    //标识—是否击中了什么
+    [NonSerialized] public bool isHit = false;
+    //箭的初速度(私用)    
+    [NonSerialized] public float mySpeed = 0;
+    //箭的初速度(公用)
+    public static float speed = GameMgr.RealSizeToGameSize(60);
+
+    //箭射出时从弓传过来的参数
+    #region 
+    //手臂弓
+    //[NonSerialized] public ArmBow armBow;
+    public float shootOffsetAngleScale;
+    //射出时的起始坐标
+    [NonSerialized] public Vector3 shootOutPosition;
+    //绝对射线
+    [NonSerialized] public RaycastHit absoluteRay;
+    //制作误差偏移角(强行制造误差,为了增加游戏难度,该偏移角的大小根据难度而定)
+    [NonSerialized] public float offsetAngle;
+    //误差偏移后的欧拉角
+    [NonSerialized] public Vector3 finalAngleAfterOffset;
+    public int playerIndex;
+    #endregion
+
+    //射线击中的靶子
+    TargetBody rayHitTargetBody;
+    //能够完美击中射线点
+    bool canPerfectHit;
+    //能否使用侧面镜头
+    [NonSerialized] public bool canUseSideCamera;
+    [NonSerialized] public ArrowCamera arrowCameraComp;
+    public System.Action onDoNextShoot;
+
+    public static HashSet<ArrowNew> arrowSet = new HashSet<ArrowNew>();
+
+    void Awake()
+    {
+        arrowSet.Add(this);
+        //GameMgr.ins.gameMode.PauseTimeCounting(this);
+        //箭模型平时属于ArmBow层,因为ArmBow层在飞行镜头中不被渲染,所以箭出去后要切换layer
+        this.transform.Find("Head/_hunse_jian").gameObject.layer = 0;
+    }
+
+    void OnDestroy()
+    {
+        arrowSet.Remove(this);
+        //if (GameMgr.ins) GameMgr.ins.gameMode.ResumeTimeCounting(this);
+    }
+
+    void Start()
+    {
+        mySpeed = speed;
+        //mySpeed *= 5;
+
+        //Billboard.ins?.SetArrowSpeed(speed);
+        //if (GameAssistUI.ins)
+        //{
+        //    mySpeed *= GameAssistUI.ins.shootScaleValue;
+        //    Billboard.ins?.SetArrowSpeedScale(GameAssistUI.ins.shootScaleValue);
+        //}
+        //Billboard.ins?.ShowSpeed();
+
+        //if (absoluteRay.transform)
+        //{
+        //    //记录射线有没有击中靶子
+        //    rayHitTargetBody = absoluteRay.transform.GetComponent<TargetBody>();
+        //    //把瞄准点画成红圈,渲染在靶子上
+        //    if (rayHitTargetBody)
+        //    {
+        //        Transform redCircle = rayHitTargetBody.transform.Find("RedCircle");
+        //        redCircle.gameObject.SetActive(true);
+        //        redCircle.transform.position = -redCircle.transform.forward * 0.001f + absoluteRay.point;
+        //    }
+        //}
+
+        SetUpBeforFly();
+
+        //Transform cameraTF = this.transform.Find("Camera");
+        //cameraTF.gameObject.SetActive(true);
+        //arrowCameraComp = cameraTF.gameObject.AddComponent<ArrowCamera>();
+        //arrowCameraComp.arrow = this;
+
+        this.activeEffectTrail(true);
+    }
+
+    /**在箭飞行前初始化&如果瞄准射线的落点在靶子上时,才调用该函数 */
+    void SetUpBeforFly()
+    {
+        //基础角
+        float baseAngleX = FormatAngleX(this.transform.eulerAngles.x);
+        //最大可调整的角度差
+        float maxDeltaAngleX = 5;
+        //最终角
+        float finalAngleX = baseAngleX;
+        //额外偏移误差角
+        float offsetAngleX = FormatAngleX(this.finalAngleAfterOffset.x) - baseAngleX;
+        float offsetAngleY = FormatAngleY(this.finalAngleAfterOffset.y - this.transform.eulerAngles.y);
+        if (DebugArrowOffsetAngle.ins)
+        {
+            offsetAngleX *= DebugArrowOffsetAngle.ins.GetOffsetScaleValue();
+            offsetAngleY *= DebugArrowOffsetAngle.ins.GetOffsetScaleValue();
+        }
+        else
+        {
+            offsetAngleX *= shootOffsetAngleScale;
+            offsetAngleY *= shootOffsetAngleScale;
+        }
+        DebugArrowOffsetAngle2.ins?.SetOffsetAngles(offsetAngleX, offsetAngleY);
+
+        if (absoluteRay.transform)
+        {
+            bool plusOffsetAngleY = false;
+            //看能否通过调整发射角让箭落在靶子的瞄准点上
+            CalculateParabolaAngle(absoluteRay.point);
+            //瞄准的是不是Target层
+            bool isTargetLayer = IsTargetLayer(absoluteRay.transform.gameObject);
+            //绝对发射角无解
+            if (!hasParabolaAngle)
+            {
+                if (isTargetLayer) AimLoadChecker.ins?.ShowOutTip();
+            }
+            else
+            {
+                //来到这里,证明发射角有解,该解姑且叫它绝对角
+                float absoluteAngleX = parabolaAngleInRadian / Mathf.PI * 180;
+                //客户要求绝对角跟原本角度相差不能超过 maxDeltaAngleX
+                float deltaAngleX = absoluteAngleX - baseAngleX;
+
+                //如果绝对角跟原本角度相差不超过maxDeltaAngleX
+                if (Mathf.Abs(deltaAngleX) < maxDeltaAngleX)
+                {
+                    finalAngleX = Mathf.Clamp(absoluteAngleX + offsetAngleX, -89, 89);
+                    plusOffsetAngleY = true;
+                    if (Math.Abs(offsetAngle) < 0.001)
+                    {
+                        canPerfectHit = true;
+                    }
+                    if (rayHitTargetBody && Mathf.RoundToInt(rayHitTargetBody.GetDistance()) >= 50 && UnityEngine.Random.value < 0.5)
+                    {
+                        canUseSideCamera = true;
+                    }
+                }
+                else
+                {
+                    finalAngleX = Mathf.Clamp(baseAngleX + maxDeltaAngleX, -89, 89);
+                    if (isTargetLayer) AimLoadChecker.ins?.ShowOutTip();
+                }
+            }
+            finalPoint = absoluteRay.point;
+            if (plusOffsetAngleY)
+            {
+                Vector3 myPos = this.transform.position;
+                Vector3 pointer = finalPoint - myPos;
+                pointer = Quaternion.AngleAxis(offsetAngleY, Vector3.up) * pointer;
+                finalPoint = myPos + pointer;
+                this.transform.LookAt(finalPoint);
+            }
+        }
+        else
+        {
+            finalPoint = this.transform.position + this.transform.forward * 100;
+        }
+
+        parabolaAngleInRadian = finalAngleX / 180 * Mathf.PI;
+    }
+
+    /*
+    因为Unity引擎的规则,向上时359~270度,向下是0~90度
+    为了方便数学运算,换算成 向上时0~90度,向下是0~-90度
+    */
+    float FormatAngleX(float value)
+    {
+        if (value > 180) value = 360 - value;
+        else value = -value;
+        return value;
+    }
+
+    /**UnityY轴旋转只有0°~360°,两个Y轴旋转相减求得的夹角时会出现>180的情况,该函数就是为了解决这问题 */
+    float FormatAngleY(float value)
+    {
+        if (Mathf.Abs(value) > 180)
+        {
+            if (value < 0)
+            {
+                return 360f + value;
+            }
+            if (value > 0)
+            {
+                return value - 360f;
+            }
+        }
+        return value;
+    }
+
+    bool IsTargetLayer(GameObject gameObject)
+    {
+        return (1 << gameObject.layer) == LayerMask.GetMask("Target");
+    }
+
+    public Transform Head()
+    {
+        return this.transform.Find("Head");
+    }
+
+    /**发射角有无解 */
+    bool hasParabolaAngle = false;
+    /**发射角弧度解 */
+    float parabolaAngleInRadian = 0;
+    /**
+        求弓箭发射到指定坐标所需要的角度。
+        已知初速度大小V,重力g,起始坐标(a1,a2),目标坐标(b1,b2)。
+        解:
+        1、列出关系式
+        Δx = b1 - a1;
+        Δy = b2 - a2;
+        Vx = V * cos(angle)
+        Vy = V * sin(angle)
+        Vy * t + 1/2 * g * t^2 = Δy
+        Vx * t = Δx
+        t = Δx / Vx
+        2、推导过程
+        (V * sin(angle)) * Δx / (V * cos(angle)) + 1/2 * g * Δx^2 / (V^2*cos(angle)^2) = Δy
+        tan(angle) * Δx + 1/2 * g * Δx^2 / (V^2*cos(angle)^2) = Δy
+        tan(angle) * Δx + 1/2 * g * (Δx^2 / V^2) * (1 + tan(angle)^2) = Δy
+        3、根据求根公式得出结论
+        a = 1/2 * g * Δx^2 / V^2
+        b = Δx
+        c = a -  Δy
+        d = tan(angle) = (-b ± (b^2 - 4*a*c)^0.5) / (2*a)
+        angle = atan(d) 
+        有无根的判别式,有根则b^2-4*a*c>=0
+    */
+    void CalculateParabolaAngle(Vector3 destination)
+    {
+        float deltaX = Vector2.Distance(
+            new Vector2(destination.x, destination.z),
+            new Vector2(this.transform.position.x, this.transform.position.z)
+        );
+        float deltaY = destination.y - this.transform.position.y;
+        float a = 0.5f * Physics.gravity.y * Mathf.Pow(deltaX, 2) / Mathf.Pow(this.mySpeed, 2);
+        float b = deltaX;
+        float c = a - deltaY;
+        hasParabolaAngle = Mathf.Pow(b, 2) - 4 * a * c >= 0;
+        if (hasParabolaAngle)
+        {
+            float res1 = (-b + Mathf.Pow(Mathf.Pow(b, 2) - 4 * a * c, 0.5f)) / (2 * a);
+            float res2 = (-b - Mathf.Pow(Mathf.Pow(b, 2) - 4 * a * c, 0.5f)) / (2 * a);
+            parabolaAngleInRadian = Mathf.Min(Mathf.Atan(res1), Mathf.Atan(res2));
+        }
+    }
+
+    void FixedUpdate()
+    {
+        if (!isHit && flyTime >= 0)
+        {
+            flyTime += Time.deltaTime;
+            if (flyTime > 14)
+            {
+                FlyTimeOut();
+            }
+        }
+    }
+    void Update()
+    {
+        UpdateFlyLogic();
+    }
+
+    void FlyTimeOut()
+    {
+        Destroy(gameObject);
+        GameController.ins.HitTarget(0);
+        nextShoot();
+    }
+
+    float logicFlyTime = 0;
+    Vector3 finalPoint;
+    /**飞行帧逻辑(运动学) */
+    void UpdateFlyLogic()
+    {
+        if (isHit) return;
+        logicFlyTime += Time.deltaTime;
+        Vector3 destination = finalPoint;
+        float vx = Mathf.Cos(parabolaAngleInRadian) * mySpeed;
+        float t = logicFlyTime;
+        float vy = Mathf.Sin(parabolaAngleInRadian) * mySpeed + Physics.gravity.y * t;
+        float dy = Mathf.Sin(parabolaAngleInRadian) * mySpeed * t + 0.5f * Physics.gravity.y * Mathf.Pow(t, 2);
+        float dx = vx * t;
+        Vector3 nextPosition = new Vector3(destination.x - shootOutPosition.x, 0, destination.z - shootOutPosition.z);
+        nextPosition = nextPosition.normalized * dx;
+        nextPosition.y = dy;
+        nextPosition = shootOutPosition + nextPosition;
+        Vector3 oldPosition = this.transform.position;
+        this.transform.position = nextPosition;
+        Vector3 eulerAngles = this.transform.eulerAngles;
+        float angleX = Mathf.Atan(vy / vx) / Mathf.PI * 180;
+        eulerAngles.x = -angleX;
+        this.transform.eulerAngles = eulerAngles;
+
+        float deltaDistance = Vector3.Distance(oldPosition, nextPosition);
+        Ray ray = new Ray(oldPosition, nextPosition - oldPosition);
+        RaycastHit raycastHit;
+        bool raycastResult = Physics.Raycast(ray, out raycastHit, deltaDistance);
+        if (raycastResult)
+        {
+            this.transform.position = raycastHit.point;
+            OnHitAnyInFlyLogic(raycastHit);
+        }
+    }
+
+    public class HitType
+    {
+        public static int None = 0;
+        public static int TargetInRing = 1; //击中了靶子,且在得分环内
+        public static int TargetOutRing = 2; //击中了靶子,但不在得分环内
+        public static int NotTarget = 4; //击中非目标对象
+        public static int Animal = 5; //击中动物
+    }
+    [NonSerialized] public int hitType = HitType.None;
+    [NonSerialized] public Transform raycastHitTransform; //射线击中的目标变换
+    [NonSerialized] public string[] hitTargetAnimalInfo;
+    //飞行逻辑中检测到碰撞
+    void OnHitAnyInFlyLogic(RaycastHit raycastHit)
+    {
+        Head().position = raycastHit.point;
+        transform.SetParent(raycastHit.transform.parent);
+        string targetName = raycastHit.transform.gameObject.name;
+        raycastHitTransform = raycastHit.transform;
+        if (targetName == "TargetBody")
+        {
+            Vector3 hitPoint = raycastHit.point;
+            if (rayHitTargetBody && canPerfectHit)
+            {
+                hitPoint = absoluteRay.point;
+                Head().position = hitPoint;
+            }
+            raycastHit.transform.GetComponent<TargetBodyNew>().Hit(this, hitPoint, playerIndex);
+        }
+        else if (raycastHit.transform.GetComponent<TargetOutBound>())
+        { //撞到空气墙当作超时处理
+            FlyTimeOut();
+        }
+        else
+        {
+            Hit();
+            GameController.ins.HitTarget(0);
+        }
+    }
+
+    public void Hit()
+    {
+        isHit = true;
+
+        if (GameDebug.ins) GameDebug.ins.ShowRes(absoluteRay.point, this.Head().position);
+
+        //控制箭的特效显示
+        this.activeEffectCyclone(false);
+        this.activeEffectBomb(true);
+        this.activeEffectTrail(false);
+
+        //最新一箭击中后会发光标记
+        //ArrowLightSick.RecoveryAll();
+        //this.GetComponentInChildren<ArrowLightSick>().Hit();
+    }
+
+    //进入下一轮射击
+    [NonSerialized] public bool hasDoneNextShoot = false;
+    public void nextShoot()
+    {
+        if (hasDoneNextShoot) return;
+        hasDoneNextShoot = true;
+
+        //try
+        //{
+        //    //if (AimHandler.ins) AimHandler.ins.Ban9AxisCalculate(false);
+        //    //把瞄准点画成红圈,渲染在靶子上(取消)
+        //    if (rayHitTargetBody)
+        //    {
+        //        Transform redCircle = rayHitTargetBody.transform.Find("RedCircle");
+        //        redCircle.gameObject.SetActive(false);
+        //    }
+        //    //最新一箭击中后会发光标记(取消)
+        //    ArrowLightSick.RecoveryAll();
+        //}
+        //catch (System.Exception e) { Debug.LogError(e.Message + "\n" + e.StackTrace); }
+
+        //if (!GameMgr.ins.gameMode.DoNextShoot()) return;
+        //this.armBow.readyShoot();
+    }
+
+    #region 箭的特效
+    void activeEffectCyclone(bool value)
+    {
+        transform.Find("Head/EF_kuosanquan").gameObject.SetActive(value);
+        if (!value) return;
+        ParticleSystemRenderer ps = transform.Find("Head/EF_kuosanquan/kuosan").GetComponent<ParticleSystemRenderer>();
+        ParticleSystemRenderer ps1 = transform.Find("Head/EF_kuosanquan/kuosan (1)").GetComponent<ParticleSystemRenderer>();
+        DOTween.To(() => ps.minParticleSize, value => {
+            ps.minParticleSize = value;
+            ps.maxParticleSize = value;
+        }, 0.4f, 0.6f);
+        DOTween.To(() => ps1.minParticleSize, value => {
+            ps1.minParticleSize = value;
+            ps1.maxParticleSize = value;
+        }, 0.8f, 0.6f);
+    }
+    void activeEffectBomb(bool value)
+    {
+        transform.Find("Head/EF_baodian").gameObject.SetActive(value);
+    }
+    void activeEffectTrail(bool value)
+    {
+        transform.Find("EF_tuowei").gameObject.SetActive(value);
+        transform.Find("EF_tuowei/Trail").GetComponent<TrailRenderer>().time = 1.6f / mySpeed;
+    }
+    #endregion
+}

+ 11 - 0
Assets/SmartBowGame/ArrowNew.cs.meta

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

+ 147 - 0
Assets/SmartBowGame/BLEView.cs

@@ -0,0 +1,147 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using SmartBowSDK;
+
+public class BLEView : MonoBehaviour
+{
+    public Button btnConnect;
+    public Button btnGyr;
+    public Button btnMag;
+    public Text textBattery;
+    public int playerIndex;
+
+    SmartBowHelper smartBowHelper;
+
+    void Start()
+    {
+        smartBowHelper = SmartBowHelper.NewInstance();
+        smartBowHelper.OnBluetoothModuleInited += () =>
+        {
+            UpdateConnectText();
+            smartBowHelper.StartRotationSensor();
+            smartBowHelper.StartShootingSensor();
+        };
+        smartBowHelper.OnBluetoothError += (error, message) =>
+        {
+            if (error == BluetoothError.ScanNotFoundTargetDevice)
+            {
+                PopupMgr.ins.ShowTip("连接失败,未发现目标设备!");
+                return;
+            }
+            PopupMgr.ins.ShowTip(message);
+        };
+        smartBowHelper.OnBluetoothStatusChanged += (oldStatus, newStatus) =>
+        {
+            if (playerIndex == 0) //1号控制
+            {
+                if (newStatus == SmartBowSDK.BluetoothStatusEnum.Connected) SimulateMouseController.ins?.SetBleConnected(true);
+                else SimulateMouseController.ins?.SetBleConnected(false);
+            }
+            UpdateConnectText();
+        };
+        smartBowHelper.OnRotationUpdate += (r) =>
+        {
+            GameController.ins.aimCrossHairs[playerIndex].UpdatePositionByModuleRotation(r);
+            if (playerIndex == 0) //1号控制
+            {
+                if (SB_EventSystem.ins && SB_EventSystem.ins.simulateMouseIsAwaked) SB_EventSystem.ins.MoveSimulateMouse(r);
+            }
+        };
+        smartBowHelper.OnShooting += OnShot;
+        smartBowHelper.OnFunctionKeyPress += () =>
+        {
+            smartBowHelper.ResetAim();
+        };
+        if (playerIndex == 0 && BluetoothWindows.IsWindows())
+            BleWinHelper.RegisterTo(smartBowHelper.gameObject);
+
+        btnConnect.onClick.AddListener(OnClick_Connect);
+        btnGyr.onClick.AddListener(OnClick_CalibrateGyr);
+        btnMag.onClick.AddListener(OnClick_CalibrateMag);
+    }
+
+    void Update()
+    {
+        UpdateCalibrateGyrText();
+        UpdateCalibrateMagText();
+        UpdateBatteryText();
+    }
+
+    float _lastShotTime = 0;
+    void OnShot(float speed)
+    {
+        if (Time.time - _lastShotTime < 1) return;
+        _lastShotTime = Time.time;
+        GameController.ins.aimCrossHairs[playerIndex].Shoot(speed);
+
+        if (playerIndex == 0) //1号控制
+        {
+            if (SB_EventSystem.ins && SB_EventSystem.ins.simulateMouseIsAwaked)
+            {
+                SB_EventSystem.ins.ClickMouse();
+            }
+        }
+    }
+
+    void UpdateConnectText()
+    {
+        Text t = btnConnect.GetComponentInChildren<Text>();
+        var newStatus = smartBowHelper.GetBluetoothStatus();
+        if (newStatus == SmartBowSDK.BluetoothStatusEnum.None) t.text = "<color=blue>未连接</color>(点击连接)";
+        if (newStatus == SmartBowSDK.BluetoothStatusEnum.Connecting) t.text = "<color=#FF670D>连接中</color>";
+        if (newStatus == SmartBowSDK.BluetoothStatusEnum.Connected)
+        {
+            if (smartBowHelper.IsBluetoothModuleInited()) t.text = "<color=green>已连接</color>(点击断开)";
+            else t.text = "<color=green>已连接</color><color=blue>(正在初始化)</color>";
+        }
+    }
+
+    void UpdateCalibrateGyrText()
+    {
+        Text text = btnGyr.GetComponentInChildren<Text>();
+        int progress = (int)(smartBowHelper.GetGyrProgress() * 100);
+        string act = smartBowHelper.IsGyrCalibrating() ? "停止" : "开始";
+        text.text = $"点击{act}陀螺仪校准({progress}%)";
+    }
+
+    void UpdateCalibrateMagText()
+    {
+        Text text = btnMag.GetComponentInChildren<Text>();
+        if (smartBowHelper.IsMagCompleted()) text.text = $"<color=green>地磁计校准完成</color>(点击重置)";
+        else
+        {
+            string tip = Time.realtimeSinceStartup - _clickCalibrateMagTime < 2 ? "<color=#FF670D>已重置</color>" : "点击重置";
+            text.text = $"<color=blue>地磁计校准中</color>({tip})";
+        }
+    }
+
+    void UpdateBatteryText()
+    {
+        //更新显示电量
+        int battery = smartBowHelper.GetBattery();
+        textBattery.text = battery > 0 ? $"电量值:{battery}" : "未获得电量值";
+    }
+
+    void OnClick_Connect()
+    {
+        var s = smartBowHelper.GetBluetoothStatus();
+        if (s == SmartBowSDK.BluetoothStatusEnum.Connecting) return;
+        else if (s == SmartBowSDK.BluetoothStatusEnum.None) smartBowHelper.Connect();
+        else if (s == SmartBowSDK.BluetoothStatusEnum.Connected) smartBowHelper.Disconnect();
+    }
+
+    void OnClick_CalibrateGyr()
+    {
+        if (smartBowHelper.IsGyrCalibrating()) smartBowHelper.StopGyrCalibration();
+        else smartBowHelper.StartGyrCalibration();
+    }
+
+    float _clickCalibrateMagTime = -100;
+    void OnClick_CalibrateMag()
+    {
+        _clickCalibrateMagTime = Time.realtimeSinceStartup;
+        smartBowHelper.StartMagCalibration();
+    }
+}

+ 11 - 0
Assets/SmartBowGame/BLEView.cs.meta

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

+ 47 - 0
Assets/SmartBowGame/DistanceSelectView.cs

@@ -0,0 +1,47 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using System;
+
+public class DistanceSelectView : MonoBehaviour
+{
+    static int[] distanceCanSelected = { 6, 8, 10, 15, 20 };
+    public Action<float> OnClickSelectDistance;
+
+    void OnEnable()
+    {
+        SimulateMouseController.ins?.AddOpenLocker(this);
+    }
+
+    void Start()
+    {
+        Transform layout = transform.Find("Layout");
+        GameObject itemPrefab = layout.Find("Item").gameObject;
+        for (int i = 1; i < distanceCanSelected.Length; i++)
+        {
+            Instantiate(
+                 itemPrefab, Vector3.zero, Quaternion.identity, transform.Find("Layout")
+             );
+        }
+        for (int i = 0; i < distanceCanSelected.Length; i++)
+        {
+            int distance = distanceCanSelected[i];
+            Transform item = layout.GetChild(i);
+            var tal = item.transform.Find("Text").GetComponent<TextAutoLanguage2>();
+            tal.textFormatArgs = new object[] { distance };
+            tal.ApplyToText();
+            Button btn = item.gameObject.GetComponent<Button>();
+            GetComponentInParent<KeyBoardNavigation>()?.buttons.Add(btn);
+            btn.onClick.AddListener(delegate () {
+                AudioMgr.ins.PlayBtn();
+                OnClickSelectDistance?.Invoke(distance);
+            });
+        }
+    }
+
+    void OnDisable()
+    {
+        SimulateMouseController.ins?.RemoveOpenLocker(this);
+    }
+}

+ 11 - 0
Assets/SmartBowGame/DistanceSelectView.cs.meta

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

+ 58 - 0
Assets/SmartBowGame/GameCanvas.cs

@@ -0,0 +1,58 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class GameCanvas : MonoBehaviour
+{
+    public Text timeText;
+    public static GameCanvas ins;
+
+    void Start()
+    {
+        ins = this;
+    }
+
+    void Update()
+    {
+        RefreshRender();
+    }
+
+    void RefreshRender()
+    {
+        RenderTime(GameController.ins.time);
+        RenderScore(0, GameController.ins.scores[0]);
+        RenderScore(1, GameController.ins.scores[1]);
+    }
+
+    void RenderTime(float time)
+    {
+        timeText.text = GetTimeStr(time);
+    }
+
+    void RenderScore(int playerIndex, float score)
+    {
+        transform.Find("ScoreBG" + (playerIndex + 1)).GetComponentInChildren<Text>().text = 
+            "玩家得分" + (float)System.Math.Round(score, CommonConfig.ringsPrecision);
+    }
+
+    string GetTimeStr(float time)
+    {
+        int seconds = (int)Mathf.Ceil(time);
+        string str = "";
+        int m = seconds / 60;
+        if (m < 10)
+        {
+            str += 0;
+        }
+        str += m;
+        str += " : ";
+        int s = seconds % 60;
+        if (s < 10)
+        {
+            str += 0;
+        }
+        str += s;
+        return str;
+    }
+}

+ 11 - 0
Assets/SmartBowGame/GameCanvas.cs.meta

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

+ 90 - 0
Assets/SmartBowGame/GameController.cs

@@ -0,0 +1,90 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+
+public class GameController : MonoBehaviour
+{
+    public AimCrossHair[] aimCrossHairs;
+    [NonSerialized] public float[] scores;
+    [NonSerialized] public float time;
+    [NonSerialized] public bool gameStart = false;
+    [NonSerialized] public bool gameOver = false;
+    [NonSerialized] public float targetDistance;
+    public GameObject arrowPrefab;
+    public static GameController ins;
+
+    void Start()
+    {
+        ins = this;
+
+        InitGame();
+        InitDistanceSelectView();
+        SetDisplayDistanceSelectView(true);
+    }
+
+    void Update()
+    {
+        if (gameStart && !gameOver)
+        {
+            if (time > 0) time -= Time.deltaTime;
+            else
+            {
+                time = 0;
+                gameOver = true;
+                //添加结算界面
+                transform.Find("PKGameSettleView").gameObject.SetActive(true);
+            }
+        }
+    }
+
+    public void HitTarget(float score, int playerIndex = -1)
+    {
+        if (!gameStart || gameOver) return;
+        if (playerIndex >= 0)
+        {
+            scores[playerIndex] += score;
+            HitTargetNumberNew.Create(score, playerIndex);
+        }
+    }
+
+    private void InitDistanceSelectView()
+    {
+        DistanceSelectView distanceSelectView = transform.Find("DistanceSelectView").GetComponent<DistanceSelectView>();
+        distanceSelectView.OnClickSelectDistance = HandleSelectDistance;
+    }
+
+    public void SetDisplayDistanceSelectView(bool active)
+    {
+        transform.Find("DistanceSelectView").gameObject.SetActive(active);
+    }
+
+    public void HandleSelectDistance(float distance)
+    {
+        SetDisplayDistanceSelectView(false);
+        targetDistance = distance;
+        foreach (var item in FindObjectsOfType<TargetBodyNew>()) item.SetDistance(distance);
+        StartGame();
+    }
+
+    public void InitGame()
+    {
+        scores = new float[] { 0, 0 };
+        time = 60;
+        gameStart = false;
+        gameOver = false;
+        foreach (var item in FindObjectsOfType<ArrowNew>())
+        {
+            if (item && item.gameObject) Destroy(item.gameObject);
+        }
+        foreach (var item in FindObjectsOfType<PointSignLastHit>())
+        {
+            if (item) item.Hide();
+        }
+    }
+
+    public void StartGame()
+    {
+        gameStart = true;
+    }
+}

+ 11 - 0
Assets/SmartBowGame/GameController.cs.meta

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

+ 32 - 0
Assets/SmartBowGame/GameEntry.cs

@@ -0,0 +1,32 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class GameEntry : MonoBehaviour
+{
+    void Awake()
+    {
+        ////设置新装app初始语言
+        //int curAppLanguage = PlayerPrefs.GetInt("AppLanguage", -1);
+        //if (curAppLanguage != CommonConfig.AppLanguage)
+        //{
+        //    PlayerPrefs.SetInt("AppLanguage", CommonConfig.AppLanguage);
+        //    PlayerPrefs.SetInt("Language", CommonConfig.AppLanguage);
+        //    Debug.Log("SetAppLanguage");
+        //}
+        PlayerPrefs.SetInt("AppLanguage", 0);
+        PlayerPrefs.SetInt("Language", 0);
+
+        Screen.orientation = ScreenOrientation.AutoRotation;//设置方向为自动(根据需要自动旋转屏幕朝向任何启用的方向。)
+        Screen.autorotateToLandscapeRight = true;           //允许自动旋转到右横屏
+        Screen.autorotateToLandscapeLeft = true;            //允许自动旋转到左横屏
+        Screen.autorotateToPortrait = false;                //不允许自动旋转到纵向
+        Screen.autorotateToPortraitUpsideDown = false;      //不允许自动旋转到纵向上下
+        Screen.sleepTimeout = SleepTimeout.NeverSleep;      //睡眠时间为从不睡眠
+        //游戏帧率设置,需要在项目设置的Quality中关闭对应画质的垂直同步(VSync选项)
+        // QualitySettings.vSyncCount = 0;
+        // Application.targetFrameRate = 60;
+        QualitySettings.vSyncCount = 1;
+        SimulateMouseController.Init();
+    }
+}

+ 11 - 0
Assets/SmartBowGame/GameEntry.cs.meta

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

+ 47 - 0
Assets/SmartBowGame/HitTargetNumberNew.cs

@@ -0,0 +1,47 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+using DG.Tweening;
+/* 击中靶子时显示的分数 */
+public class HitTargetNumberNew : MonoBehaviour
+{
+    void Start()
+    {
+        DoText();
+    }
+
+    void DoText()
+    {
+        RectTransform rtf = this.transform.GetComponentInChildren<Text>().rectTransform;
+        Sequence seq = DOTween.Sequence();
+        float scale1 = rtf.localScale.x * 3.3f;
+        float scale2 = rtf.localScale.x;
+        rtf.localScale = Vector3.zero;
+        seq.Append(rtf.DOScale(new Vector3(scale1, scale1, 0), 0.1f));
+        seq.Append(rtf.DOScale(new Vector3(scale2, scale2, 0), 0.1f));
+        seq.AppendInterval(1f);
+        seq.Append(rtf.GetComponent<Text>().DOFade(0, 0.23f));
+        seq.AppendCallback(delegate () {
+            Destroy(gameObject);
+        });
+    }
+
+    public static void Create(float number, int pid)
+    {
+        if (number <= 0) return;
+        string oName = "HitTargetNumber" + pid;
+        var exist = GameObject.Find(oName);
+        if (exist && exist.gameObject) Destroy(exist); 
+        GameObject o = Instantiate(
+            Resources.Load<GameObject>("Prefabs/Effects/" + oName),
+            Vector3.zero,
+            Quaternion.identity,
+            GameObject.Find("GameCanvas").transform
+        );
+        o.name = oName;
+        o.transform.localPosition = new Vector3(-320, 80, 0);
+        if (pid == 1) o.transform.localPosition = new Vector3(320, 80, 0);
+        o.GetComponentInChildren<Text>().text = number.ToString($"f{CommonConfig.ringsPrecision}");
+    }
+}

+ 11 - 0
Assets/SmartBowGame/HitTargetNumberNew.cs.meta

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

+ 54 - 0
Assets/SmartBowGame/PKGameSettleViewNew.cs

@@ -0,0 +1,54 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class PKGameSettleViewNew : MonoBehaviour
+{
+    // Start is called before the first frame update
+    void OnEnable()
+    {
+        SimulateMouseController.ins?.AddOpenLocker(this);
+        int[] pkResults = { 0, 0 };
+        var gc = GameController.ins;
+        if (gc.scores[0] > gc.scores[1])
+        {
+            pkResults[0] = 1;
+            pkResults[1] = -1;
+        }
+        else if (gc.scores[0] < gc.scores[1])
+        {
+            pkResults[0] = -1;
+            pkResults[1] = 1;
+        }
+        for (int i = 1; i <= 2; i++)
+        {
+            int index = i - 1;
+            transform.Find("Win" + i).gameObject.SetActive(pkResults[index] == 1);
+            transform.Find("Fail" + i).gameObject.SetActive(pkResults[index] == -1);
+            transform.Find("Draw" + i).gameObject.SetActive(pkResults[index] == 0);
+            transform.Find("Score" + i + "/Text").GetComponent<Text>().text = gc.scores[index].ToString();
+        }
+    }
+
+    void OnDisable()
+    {
+        SimulateMouseController.ins?.RemoveOpenLocker(this);
+    }
+
+    public void OnClick_Again()
+    {
+        gameObject.SetActive(false);
+        AudioMgr.ins.PlayBtn();
+        GameController.ins.InitGame();
+        GameController.ins.HandleSelectDistance(GameController.ins.targetDistance);
+    }
+
+    public void OnClick_Back()
+    {
+        gameObject.SetActive(false);
+        AudioMgr.ins.PlayBtn();
+        GameController.ins.InitGame();
+        GameController.ins.SetDisplayDistanceSelectView(true);
+    }
+}

+ 11 - 0
Assets/SmartBowGame/PKGameSettleViewNew.cs.meta

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

+ 60 - 0
Assets/SmartBowGame/TargetBodyNew.cs

@@ -0,0 +1,60 @@
+using UnityEngine;
+/* 组件-射击目标-靶子 */
+public class TargetBodyNew : MonoBehaviour
+{
+    float distance = 10f;
+    public int playerIndex;
+    public static TargetBodyNew ins;
+
+    void Start()
+    {
+        ins = this;
+        SetDistance(distance);
+    }
+
+    void OnDestroy()
+    {
+        if (ins == this) ins = null;
+    }
+
+    public void Hit(ArrowNew arrow, Vector3 hitPosition, int attackerPlayerIndex)
+    {
+        transform.Find("PointSignLastHit")?.GetComponent<PointSignLastHit>()?.Show(hitPosition);
+        arrow.Hit();
+        AudioMgr.ins.PlayHit(AudioMgr.GetAudioSource(gameObject));
+        bool hitTarget = false;
+
+        float maxSize = Vector3.Distance(transform.Find("CenterPoint").position, transform.Find("SidePoint").position);
+        float radius = measureRadius(hitPosition);
+        float score = Mathf.Clamp(10f - radius / maxSize * 10f, 0, 9.9f) + 1;
+        if (score >= 1)
+        {
+            score = (float)System.Math.Round(score, CommonConfig.ringsPrecision);
+            if (playerIndex != attackerPlayerIndex) score = 0;
+            GameController.ins.HitTarget(score, attackerPlayerIndex);
+            //AudioMgr.ins.PlayCheer(true);
+            hitTarget = true;
+        }
+
+        if (!hitTarget) GameController.ins.HitTarget(0);
+        arrow.hitType = hitTarget ? Arrow.HitType.TargetInRing : Arrow.HitType.TargetOutRing;
+    }
+
+    float measureRadius(Vector3 position)
+    {
+        return Vector3.Distance(transform.Find("CenterPoint").position, position);
+    }
+
+    public void SetDistance(float value)
+    {
+        distance = value;
+        Vector3 v3 = transform.parent.localPosition;
+        v3.z = GameMgr.RealSizeToGameSize(value);
+        transform.parent.localPosition = v3;
+    }
+
+    public float GetDistance()
+    {
+        return distance;
+    }
+}

+ 11 - 0
Assets/SmartBowGame/TargetBodyNew.cs.meta

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

+ 8 - 0
Assets/SmartBowSDK.meta

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

+ 454 - 0
Assets/SmartBowSDK/BleWinHelper.cs

@@ -0,0 +1,454 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using UnityEngine;
+using System.Runtime.InteropServices;
+
+namespace SmartBowSDK
+{
+    /// <summary>
+    /// Windows连接BluetoothLE
+    /// 我的扫描逻辑默认了读写特征都在同一服务下
+    /// </summary>
+    public class BleWinHelper : MonoBehaviour
+    {
+        private const string LogTag = "BleWinHelper-Log: ";
+        private static void Log(string text)
+        {
+            Debug.Log(LogTag + text);
+        }
+        private static void Warn(string text)
+        {
+            Debug.LogWarning(LogTag + text);
+        }
+        private static void Error(string text)
+        {
+            Debug.Log(LogTag + text);
+        }
+
+        private string targetDeviceName = "Bbow_20210501";
+        private string targetService = "{0000fff0-0000-1000-8000-00805f9b34fb}";
+        private string targetCharacteristicsNotify = "{0000fff1-0000-1000-8000-00805f9b34fb}";
+        private string targetCharacteristicsWrite = "{0000fff2-0000-1000-8000-00805f9b34fb}";
+
+        private bool isConnectLocking = false;
+        private bool isScanningDevices = false;
+        private bool isScanningServices = false;
+        private bool isScanningCharacteristics = false;
+        private bool isSubscribed = false;
+        private bool isSubscribing = false;
+
+        private string lastError = null;
+
+        private string selectedDeviceId = null;
+
+        private Dictionary<string, Dictionary<string, string>> deviceList = new Dictionary<string, Dictionary<string, string>>();
+        private List<string> serviceList = new List<string>();
+        private List<string> characteristicsList = new List<string>();
+
+        private float _connectedTime = 0;
+        private float _receiveDataTime = 0;
+        private float _heartBeatInterval = 0;
+
+        private Action OnConnected;
+        /// <summary>
+        /// 主动调用Disconnect()不会触发该委托
+        /// </summary>
+        private Action OnConnectionFailed;
+        private Action<byte[]> OnCharacteristicChanged;
+
+        public static BleWinHelper RegisterTo(GameObject o)
+        {
+            if (_Instance)
+            {
+                Error("Register fail, because only one can be registered.");
+                return null;
+            }
+            BleWinHelper comp = o.AddComponent<BleWinHelper>();
+            BluetoothWindows.Connect = comp.Connect;
+            BluetoothWindows.Disconnect = comp.Disconnect;
+            BluetoothWindows.Write = comp.Write;
+            comp.OnConnected = () => BluetoothWindows.OnConnected?.Invoke();
+            comp.OnConnectionFailed = () => BluetoothWindows.OnConnectionFailed?.Invoke();
+            comp.OnCharacteristicChanged = (bytes) => BluetoothWindows.OnCharacteristicChanged?.Invoke(bytes);
+            return comp;
+        }
+
+        /// <summary>
+        /// 设置心跳检测
+        /// 1.每次收到的蓝牙数据都视为心跳
+        /// 2.帮助触发蓝牙断开监听
+        /// </summary>
+        /// <param name="interval">心跳检测间隔</param>
+        public void SetHeartBeat(float interval)
+        {
+            _heartBeatInterval = interval;
+        }
+
+        private static BleWinHelper _Instance;
+
+        void Awake()
+        {
+            _Instance = this;
+        }
+
+        void OnDestroy()
+        {
+            if (_Instance == this) _Instance = null;
+            BleApi.Quit();
+        }
+
+        void Update()
+        {
+            BleApi.ScanStatus status;
+            if (isScanningDevices)
+            {
+                BleApi.DeviceUpdate res = new BleApi.DeviceUpdate();
+                do
+                {
+                    status = BleApi.PollDevice(ref res, false);
+                    if (status == BleApi.ScanStatus.AVAILABLE)
+                    {
+                        if (!deviceList.ContainsKey(res.id))
+                            deviceList[res.id] = new Dictionary<string, string>() {
+                            { "name", "" },
+                            { "isConnectable", "False" }
+                        };
+                        if (res.nameUpdated)
+                            deviceList[res.id]["name"] = res.name;
+                        if (res.isConnectableUpdated)
+                            deviceList[res.id]["isConnectable"] = res.isConnectable.ToString();
+                        if (deviceList[res.id]["name"] == targetDeviceName && deviceList[res.id]["isConnectable"] == "True")
+                        {
+                            selectedDeviceId = res.id;
+                            StopDeviceScan();
+                        }
+                    }
+                    else if (status == BleApi.ScanStatus.FINISHED)
+                    {
+                        StartCoroutine(ScanServiceAndCharacteristicsToSubscribe());
+                    }
+                } while (status == BleApi.ScanStatus.AVAILABLE);
+            }
+            if (isScanningServices)
+            {
+                BleApi.Service res;
+                do
+                {
+                    status = BleApi.PollService(out res, false);
+                    if (status == BleApi.ScanStatus.AVAILABLE)
+                    {
+                        serviceList.Add(res.uuid);
+                    }
+                    else if (status == BleApi.ScanStatus.FINISHED)
+                    {
+                        isScanningServices = false;
+                    }
+                } while (status == BleApi.ScanStatus.AVAILABLE);
+            }
+            if (isScanningCharacteristics)
+            {
+                BleApi.Characteristic res;
+                do
+                {
+                    status = BleApi.PollCharacteristic(out res, false);
+                    if (status == BleApi.ScanStatus.AVAILABLE)
+                    {
+                        string name = res.userDescription != "no description available" ? res.userDescription : res.uuid;
+                        characteristicsList.Add(name);
+                    }
+                    else if (status == BleApi.ScanStatus.FINISHED)
+                    {
+                        isScanningCharacteristics = false;
+                    }
+                } while (status == BleApi.ScanStatus.AVAILABLE);
+            }
+            if (isSubscribed)
+            {
+                BleApi.BLEData res;
+                while (BleApi.PollData(out res, false))
+                {
+                    //string text = BitConverter.ToString(res.buf, 0, res.size);
+                    // string text = Encoding.ASCII.GetString(res.buf, 0, res.size);
+                    byte[] bytes = new byte[res.size];
+                    Array.Copy(res.buf, bytes, res.size);
+                    _receiveDataTime = Time.realtimeSinceStartup;
+                    OnCharacteristicChanged?.Invoke(bytes);
+                }
+            }
+            {
+                BleApi.ErrorMessage res;
+                BleApi.GetError(out res);
+                if (lastError != res.msg)
+                {
+                    Error(res.msg);
+                    lastError = res.msg;
+                    if (lastError.Contains("SendDataAsync") && isSubscribed)
+                    {
+                        HandleConnectFail();
+                    }
+                }
+            }
+        }
+
+        void LateUpdate()
+        {
+            if (
+                _heartBeatInterval > 0 && 
+                isSubscribed && 
+                Time.realtimeSinceStartup - _connectedTime >= _heartBeatInterval &&
+                Time.realtimeSinceStartup - _receiveDataTime >= _heartBeatInterval
+            ) HandleConnectFail();
+        }
+
+        private bool Connect()
+        {
+            if (isConnectLocking || isScanningDevices)
+            {
+                Warn("Connect Invalid, because is in connect.");
+                return false;
+            }
+            BleApi.StartDeviceScan();
+            isConnectLocking = true;
+            isScanningDevices = true;
+            Log("Start Connect");
+            return true;
+        }
+
+        private void StopDeviceScan()
+        {
+            if (!isScanningDevices) return;
+            BleApi.StopDeviceScan();
+            isScanningDevices = false;
+        }
+
+        private IEnumerator ScanServiceAndCharacteristicsToSubscribe()
+        {
+            isSubscribing = true;
+
+            if (selectedDeviceId == null)
+            {
+                HandleConnectFail();
+                yield break;
+            }
+            Log("SelectedDeviceId OK");
+
+            BleApi.ScanServices(selectedDeviceId);
+            isScanningServices = true;
+            serviceList.Clear();
+
+            while (isScanningServices) yield return null;
+
+            bool findTargetService = false;
+
+            foreach (string service in serviceList)
+            {
+                if (service == targetService)
+                {
+                    findTargetService = true;
+                    Log("FindTargetService OK");
+                    break;
+                }
+            }
+
+            if (!findTargetService)
+            {
+                HandleConnectFail();
+                yield break;
+            }
+
+            BleApi.ScanCharacteristics(selectedDeviceId, targetService);
+            isScanningCharacteristics = true;
+            characteristicsList.Clear();
+
+            while (isScanningCharacteristics) yield return null;
+
+            bool findTargetCharacteristicsNotify = false;
+            bool findTargetCharacteristicsWrite = false;
+
+            foreach (string characteristics in characteristicsList)
+            {
+                if (characteristics == targetCharacteristicsNotify)
+                {
+                    findTargetCharacteristicsNotify = true;
+                    Log("FindTargetCharacteristicsNotify OK");
+                }
+                else if (characteristics == targetCharacteristicsWrite)
+                {
+                    findTargetCharacteristicsWrite = true;
+                    Log("FindTargetCharacteristicsWrite OK");
+                }
+            }
+
+            if (!findTargetCharacteristicsNotify || !findTargetCharacteristicsWrite)
+            {
+                HandleConnectFail();
+                yield break;
+            }
+
+            BleApi.SubscribeCharacteristic(selectedDeviceId, targetService, targetCharacteristicsNotify, false);
+            isSubscribed = true;
+            isSubscribing = false;
+            Log("SubscribeCharacteristicNotify OK");
+
+            _connectedTime = Time.realtimeSinceStartup;
+            OnConnected?.Invoke();
+        }
+
+        private void HandleConnectFail()
+        {
+            if (selectedDeviceId != null) BleApi.Disconnect(selectedDeviceId);
+            bool isLockBefore = isConnectLocking;
+            ReinitAfterConnectFail();
+            if (isLockBefore) OnConnectionFailed?.Invoke();
+        }
+
+        private void ReinitAfterConnectFail()
+        {
+            isConnectLocking = false;
+            isScanningDevices = false;
+            isScanningServices = false;
+            isScanningCharacteristics = false;
+            isSubscribed = false;
+            isSubscribing = false;
+            selectedDeviceId = null;
+            deviceList.Clear();
+            serviceList.Clear();
+            characteristicsList.Clear();
+        }
+
+        private bool Write(string text)
+        {
+            if (!isSubscribed) return false;
+            byte[] payload = Encoding.ASCII.GetBytes(text);
+            BleApi.BLEData data = new BleApi.BLEData();
+            data.buf = new byte[512];
+            data.size = (short)payload.Length;
+            data.deviceId = selectedDeviceId;
+            data.serviceUuid = targetService;
+            data.characteristicUuid = targetCharacteristicsWrite;
+            for (int i = 0; i < payload.Length; i++)
+                data.buf[i] = payload[i];
+            // no error code available in non-blocking mode
+            BleApi.SendData(in data, false);
+            Log("Write(" + text + ")");
+            return true;
+        }
+
+        private bool Disconnect()
+        {
+            if (!isConnectLocking)
+            {
+                Warn("Disconnect Invalid, because not in connect.");
+                return false;
+            }
+            if (isSubscribing)
+            {
+                Warn("Disconnect Invalid, because is subscribing.");
+                return false;
+            }
+            if (isScanningDevices) StopDeviceScan();
+            if (selectedDeviceId != null) BleApi.Disconnect(selectedDeviceId);
+            ReinitAfterConnectFail();
+            Log("Disconnect OK");
+            return true;
+        }
+    }
+    public class BleApi
+    {
+        public enum ScanStatus { PROCESSING, AVAILABLE, FINISHED };
+
+        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+        public struct DeviceUpdate
+        {
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
+            public string id;
+            [MarshalAs(UnmanagedType.I1)]
+            public bool isConnectable;
+            [MarshalAs(UnmanagedType.I1)]
+            public bool isConnectableUpdated;
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
+            public string name;
+            [MarshalAs(UnmanagedType.I1)]
+            public bool nameUpdated;
+        }
+
+        [DllImport("BleWinrtDll.dll", EntryPoint = "StartDeviceScan")]
+        public static extern void StartDeviceScan();
+
+        [DllImport("BleWinrtDll.dll", EntryPoint = "PollDevice")]
+        public static extern ScanStatus PollDevice(ref DeviceUpdate device, bool block);
+
+        [DllImport("BleWinrtDll.dll", EntryPoint = "StopDeviceScan")]
+        public static extern void StopDeviceScan();
+
+        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+        public struct Service
+        {
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
+            public string uuid;
+        };
+
+        [DllImport("BleWinrtDll.dll", EntryPoint = "ScanServices", CharSet = CharSet.Unicode)]
+        public static extern void ScanServices(string deviceId);
+
+        [DllImport("BleWinrtDll.dll", EntryPoint = "PollService")]
+        public static extern ScanStatus PollService(out Service service, bool block);
+
+        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+        public struct Characteristic
+        {
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
+            public string uuid;
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
+            public string userDescription;
+        };
+
+        [DllImport("BleWinrtDll.dll", EntryPoint = "ScanCharacteristics", CharSet = CharSet.Unicode)]
+        public static extern void ScanCharacteristics(string deviceId, string serviceId);
+
+        [DllImport("BleWinrtDll.dll", EntryPoint = "PollCharacteristic")]
+        public static extern ScanStatus PollCharacteristic(out Characteristic characteristic, bool block);
+
+        [DllImport("BleWinrtDll.dll", EntryPoint = "SubscribeCharacteristic", CharSet = CharSet.Unicode)]
+        public static extern bool SubscribeCharacteristic(string deviceId, string serviceId, string characteristicId, bool block);
+
+        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+        public struct BLEData
+        {
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
+            public byte[] buf;
+            [MarshalAs(UnmanagedType.I2)]
+            public short size;
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+            public string deviceId;
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+            public string serviceUuid;
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+            public string characteristicUuid;
+        };
+
+        [DllImport("BleWinrtDll.dll", EntryPoint = "PollData")]
+        public static extern bool PollData(out BLEData data, bool block);
+
+        [DllImport("BleWinrtDll.dll", EntryPoint = "SendData")]
+        public static extern bool SendData(in BLEData data, bool block);
+
+        [DllImport("BleWinrtDll.dll", EntryPoint = "Disconnect", CharSet = CharSet.Unicode)]
+        public static extern void Disconnect(string deviceId);
+
+        [DllImport("BleWinrtDll.dll", EntryPoint = "Quit")]
+        public static extern void Quit();
+
+        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+        public struct ErrorMessage
+        {
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
+            public string msg;
+        };
+
+        [DllImport("BleWinrtDll.dll", EntryPoint = "GetError")]
+        public static extern void GetError(out ErrorMessage buf);
+    }
+}

+ 11 - 0
Assets/SmartBowSDK/BleWinHelper.cs.meta

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

二進制
Assets/SmartBowSDK/BleWinrtDll.dll


+ 27 - 0
Assets/SmartBowSDK/BleWinrtDll.dll.meta

@@ -0,0 +1,27 @@
+fileFormatVersion: 2
+guid: 44462cf36f179cc4caa1f698f0c93717
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  defineConstraints: []
+  isPreloaded: 0
+  isOverridable: 0
+  isExplicitlyReferenced: 0
+  validateReferences: 1
+  platformData:
+  - first:
+      Any: 
+    second:
+      enabled: 1
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 0
+      settings:
+        DefaultValueInitialized: true
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

二進制
Assets/SmartBowSDK/SmartBowSDK.dll


+ 33 - 0
Assets/SmartBowSDK/SmartBowSDK.dll.meta

@@ -0,0 +1,33 @@
+fileFormatVersion: 2
+guid: a1779a517693f6049be1b24be1538ac2
+PluginImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  iconMap: {}
+  executionOrder: {}
+  defineConstraints: []
+  isPreloaded: 0
+  isOverridable: 0
+  isExplicitlyReferenced: 0
+  validateReferences: 1
+  platformData:
+  - first:
+      Any: 
+    second:
+      enabled: 1
+      settings: {}
+  - first:
+      Editor: Editor
+    second:
+      enabled: 0
+      settings:
+        DefaultValueInitialized: true
+  - first:
+      Windows Store Apps: WindowsStoreApps
+    second:
+      enabled: 0
+      settings:
+        CPU: AnyCPU
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 4 - 0
Assets/SmartBowSDK/link.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<linker>
+   <assembly fullname="SmartBowSDK" preserve="all"/>
+</linker>

+ 7 - 0
Assets/SmartBowSDK/link.xml.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: d093bb84681f0a24d9853cbc625a11da
+TextScriptImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 10 - 5
Assets/ThirdAssets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset

@@ -2,14 +2,15 @@
 %TAG !u! tag:unity3d.com,2011:
 --- !u!21 &2180264
 Material:
-  serializedVersion: 6
+  serializedVersion: 8
   m_ObjectHideFlags: 0
   m_CorrespondingSourceObject: {fileID: 0}
   m_PrefabInstance: {fileID: 0}
   m_PrefabAsset: {fileID: 0}
   m_Name: LiberationSans SDF Material
   m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3}
-  m_ShaderKeywords: 
+  m_ValidKeywords: []
+  m_InvalidKeywords: []
   m_LightmapFlags: 1
   m_EnableInstancingVariants: 0
   m_DoubleSidedGI: 0
@@ -108,9 +109,9 @@ Material:
     - _Parallax: 0.02
     - _PerspectiveFilter: 0.875
     - _Reflectivity: 10
-    - _ScaleRatioA: 0.90909094
+    - _ScaleRatioA: 0.9
     - _ScaleRatioB: 0.73125
-    - _ScaleRatioC: 0.7386364
+    - _ScaleRatioC: 0.73125
     - _ScaleX: 1
     - _ScaleY: 1
     - _ShaderFlags: 0
@@ -176,6 +177,7 @@ MonoBehaviour:
     m_StyleName: Regular
     m_PointSize: 86
     m_Scale: 1
+    m_UnitsPerEM: 0
     m_LineHeight: 98.8916
     m_AscentLine: 77.853516
     m_CapLine: 59
@@ -316,7 +318,7 @@ Texture2D:
   m_ForcedFallbackFormat: 4
   m_DownscaleFallback: 0
   m_IsAlphaChannelOptional: 0
-  serializedVersion: 2
+  serializedVersion: 3
   m_Width: 0
   m_Height: 0
   m_CompleteImageSize: 0
@@ -350,3 +352,6 @@ Texture2D:
     offset: 0
     size: 0
     path: 
+  m_OriginalWidth: 0
+  m_OriginalHeight: 0
+  m_OriginalAssetGuid: 00000000000000000000000000000000

+ 5 - 14
ProjectSettings/EditorBuildSettings.asset

@@ -5,31 +5,22 @@ EditorBuildSettings:
   m_ObjectHideFlags: 0
   serializedVersion: 2
   m_Scenes:
-  - enabled: 1
+  - enabled: 0
     path: Assets/BowArrow/Scenes/Entry.unity
     guid: 14a16d0455f1bf44a8cf4e02c0550a99
-  - enabled: 1
+  - enabled: 0
     path: Assets/BowArrow/Scenes/Login.unity
     guid: 200a793b1fc5aac438c87e1b342a939a
-  - enabled: 1
+  - enabled: 0
     path: Assets/BowArrow/Scenes/Home.unity
     guid: 8aa5affa1b256294a8c908dbab6122d0
   - enabled: 1
     path: Assets/BowArrow/Scenes/Game.unity
     guid: 3ee64920a7ce6dd4782fcc656bb2b337
-  - enabled: 1
+  - enabled: 0
     path: Assets/BowArrow/Scenes/GameChallengeScene/GameChallenge.unity
     guid: 983e1d3256c7dbe49accee6b31bb6d07
-  - enabled: 1
+  - enabled: 0
     path: Assets/BowArrow/Scenes/GameChallengeScene/GameChallengeNightEnv.unity
     guid: eaefd9b800b58ce4dbb99498871991ca
-  - enabled: 1
-    path: Assets/DuckHunter/Scenes/DuckHunter.unity
-    guid: 9920b6e59e0690940a0130b75073a1ea
-  - enabled: 1
-    path: Assets/WildAttack/Scenes/WildAttack.unity
-    guid: 9fc0d4010bbf28b4594072e72b8655ab
-  - enabled: 1
-    path: Assets/FruitMaster/Scenes/FruitMaster.unity
-    guid: 5600e697996c4b64b8ca124f15f30a58
   m_configObjects: {}

Some files were not shown because too many files changed in this diff