using System; using UnityEngine; using UnityEngine.UI; public class ShootCheck : MonoBehaviour { float[] accList = new float[30]; int dataCount = 0; float gravity = 0; float maxAcc = 0; bool hasReachShootThreshold = false; bool locked = false; int hitCount = 0; float rangeAcc; //最新几帧的平均值 [SerializeField] Text text; public float shootSpeed; public static ShootCheck ins; void Start() { ins = this; BluetoothDispatcher.shoot = OnDataReceived; } void OnDestroy() { ins = null; } float[] ays = new float[4]; public void OnDataReceived(byte[] bytes) { Debug.Log("射击模块数据长度" + bytes.Length); ays[0] = ToAcceleratedSpeed(bytes[7], bytes[8]); ays[1] = ToAcceleratedSpeed(bytes[17], bytes[18]); ays[2] = ToAcceleratedSpeed(bytes[27], bytes[28]); ays[3] = ToAcceleratedSpeed(bytes[37], bytes[38]); foreach (float ay in ays) { try { if (ins.check(ay)) { if (ArmBow.ins != null) { ArmBow.ins.ADS_fire(); } } } catch (Exception e) { Debug.Log(e.Message); } } } float ToAcceleratedSpeed(byte b1, byte b2) { int value = TwoByteToInt(b1, b2); return (float)value / 32768 * 16; } int TwoByteToInt(byte b1, byte b2) { ushort twoByte = (ushort)(b1 * 256 + b2); short shortNum = (short)twoByte; return (int)shortNum; } int validFrameCount = 0; bool check(float acc) { DebugLine.show(acc); DebugLine.showSteady(gravity); for (int i = accList.Length - 1; i > 0; i--) { accList[i] = accList[i - 1]; } accList[0] = acc; dataCount++; if (locked) { return false; } if (hasReachShootThreshold) { validFrameCount++; if (acc <= gravity) { hitCount++; shootSpeed = maxAcc - gravity; Log("第" + hitCount + "次识别射箭\n过滤正轴重力" + gravity.ToString("#0.000") + "后\n所得最大加速度峰值" + (maxAcc - gravity).ToString("#0.000") + "\n有效帧数" + validFrameCount); maxAcc = 0; validFrameCount = 0; hasReachShootThreshold = false; Dolock(); Invoke("Unlock", 0.8f); return true; } else if (acc > maxAcc) { maxAcc = acc; } if (validFrameCount > 20) { maxAcc = 0; validFrameCount = 0; hasReachShootThreshold = false; Log("不符合短时间爆发加速"); } // if (this.isSteady()) { // hitCount++; // shootSpeed = integral / 16f; // Log("第" + hitCount + "次识别射箭\n振幅:" + integral); // integral = 0; // validFrameCount = 0; // hasReachShootThreshold = false; // return true; // } else { // integral += Mathf.Abs(acc - gravity); // } return false; } if (dataCount > steadyFrameCount) { if (isSteady()) { gravity = Mathf.Clamp(rangeAcc, -0.981f, 0.981f); } if (acc - gravity > 2) { hasReachShootThreshold = true; maxAcc = acc; // integral += Mathf.Abs(acc - gravity); } } return false; } // float integral = 0; int steadyFrameCount = 6; bool isSteady() { float totalAcc = 0; for (int i = 0; i < steadyFrameCount; i++) { totalAcc += accList[i]; } rangeAcc = totalAcc / steadyFrameCount; float squareAcc = 0; for (int i = 0; i < steadyFrameCount; i++) { squareAcc += (float) Mathf.Pow(accList[i] - rangeAcc, 2); } squareAcc /= steadyFrameCount; return squareAcc < 0.00012; } void Dolock() { this.locked = true; } void Unlock() { this.locked = false; } void Log(string text) { if (this.text != null) { this.text.text = text; } else { Debug.Log(text); } } }