ShootCheck.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.UI;
  4. public class ShootCheck : MonoBehaviour
  5. {
  6. float[] accList = new float[30];
  7. int dataCount = 0;
  8. float gravity = 0;
  9. float maxAcc = 0;
  10. bool hasReachShootThreshold = false;
  11. bool locked = false;
  12. int hitCount = 0;
  13. float rangeAcc; //最新几帧的平均值
  14. [SerializeField] Text text;
  15. public float shootSpeed;
  16. public static ShootCheck ins;
  17. void Start()
  18. {
  19. ins = this;
  20. BluetoothDispatcher.shoot = OnDataReceived;
  21. }
  22. void OnDestroy()
  23. {
  24. ins = null;
  25. }
  26. float[] ays = new float[4];
  27. public void OnDataReceived(byte[] bytes) {
  28. Debug.Log("射击模块数据长度" + bytes.Length);
  29. ays[0] = ToAcceleratedSpeed(bytes[7], bytes[8]);
  30. ays[1] = ToAcceleratedSpeed(bytes[17], bytes[18]);
  31. ays[2] = ToAcceleratedSpeed(bytes[27], bytes[28]);
  32. ays[3] = ToAcceleratedSpeed(bytes[37], bytes[38]);
  33. foreach (float ay in ays)
  34. {
  35. try
  36. {
  37. if (ins.check(ay))
  38. {
  39. if (ArmBow.ins != null)
  40. {
  41. ArmBow.ins.ADS_fire();
  42. }
  43. }
  44. }
  45. catch (Exception e)
  46. {
  47. Debug.Log(e.Message);
  48. }
  49. }
  50. }
  51. float ToAcceleratedSpeed(byte b1, byte b2)
  52. {
  53. int value = TwoByteToInt(b1, b2);
  54. return (float)value / 32768 * 16;
  55. }
  56. int TwoByteToInt(byte b1, byte b2)
  57. {
  58. ushort twoByte = (ushort)(b1 * 256 + b2);
  59. short shortNum = (short)twoByte;
  60. return (int)shortNum;
  61. }
  62. int validFrameCount = 0;
  63. bool check(float acc)
  64. {
  65. DebugLine.show(acc);
  66. DebugLine.showSteady(gravity);
  67. for (int i = accList.Length - 1; i > 0; i--)
  68. {
  69. accList[i] = accList[i - 1];
  70. }
  71. accList[0] = acc;
  72. dataCount++;
  73. if (locked)
  74. {
  75. return false;
  76. }
  77. if (hasReachShootThreshold) {
  78. validFrameCount++;
  79. if (acc <= gravity) {
  80. hitCount++;
  81. shootSpeed = maxAcc - gravity;
  82. Log("第" + hitCount + "次识别射箭\n过滤正轴重力" + gravity.ToString("#0.000") + "后\n所得最大加速度峰值" + (maxAcc - gravity).ToString("#0.000") + "\n有效帧数" + validFrameCount);
  83. maxAcc = 0;
  84. validFrameCount = 0;
  85. hasReachShootThreshold = false;
  86. Dolock();
  87. Invoke("Unlock", 0.8f);
  88. return true;
  89. } else if (acc > maxAcc) {
  90. maxAcc = acc;
  91. }
  92. if (validFrameCount > 20)
  93. {
  94. maxAcc = 0;
  95. validFrameCount = 0;
  96. hasReachShootThreshold = false;
  97. Log("不符合短时间爆发加速");
  98. }
  99. // if (this.isSteady()) {
  100. // hitCount++;
  101. // shootSpeed = integral / 16f;
  102. // Log("第" + hitCount + "次识别射箭\n振幅:" + integral);
  103. // integral = 0;
  104. // validFrameCount = 0;
  105. // hasReachShootThreshold = false;
  106. // return true;
  107. // } else {
  108. // integral += Mathf.Abs(acc - gravity);
  109. // }
  110. return false;
  111. }
  112. if (dataCount > steadyFrameCount)
  113. {
  114. if (isSteady())
  115. {
  116. gravity = Mathf.Clamp(rangeAcc, -0.981f, 0.981f);
  117. }
  118. if (acc - gravity > 2)
  119. {
  120. hasReachShootThreshold = true;
  121. maxAcc = acc;
  122. // integral += Mathf.Abs(acc - gravity);
  123. }
  124. }
  125. return false;
  126. }
  127. // float integral = 0;
  128. int steadyFrameCount = 6;
  129. bool isSteady() {
  130. float totalAcc = 0;
  131. for (int i = 0; i < steadyFrameCount; i++)
  132. {
  133. totalAcc += accList[i];
  134. }
  135. rangeAcc = totalAcc / steadyFrameCount;
  136. float squareAcc = 0;
  137. for (int i = 0; i < steadyFrameCount; i++)
  138. {
  139. squareAcc += (float) Mathf.Pow(accList[i] - rangeAcc, 2);
  140. }
  141. squareAcc /= steadyFrameCount;
  142. return squareAcc < 0.00012;
  143. }
  144. void Dolock()
  145. {
  146. this.locked = true;
  147. }
  148. void Unlock()
  149. {
  150. this.locked = false;
  151. }
  152. void Log(string text)
  153. {
  154. if (this.text != null)
  155. {
  156. this.text.text = text;
  157. } else {
  158. Debug.Log(text);
  159. }
  160. }
  161. }