using System; using System.Collections; using System.Collections.Generic; using BehaviorDesigner.Runtime.Tasks; using TruegearSdk; using UnityEngine; public class TrueGearEffectManager : MonoBehaviour { public static TrueGearEffectManager Ins; // 马甲功能开关(在Unity编辑器中配置) [SerializeField] private bool enableTrueGear = false; /// /// 是否启用TrueGear马甲功能 /// public bool EnableTrueGear => enableTrueGear; private void Awake() { Ins = this; isAvailableIndex = 20; GetConnectIndex = 20; AddHitPart(); // 不再自动连接,等待用户选择设备后再连接 } private void Start() { } /// /// 初始化TrueGear蓝牙(仅初始化,不连接) /// public void InitTrueGear() { TruegearAndroidConnector androidConnector = new TruegearAndroidConnector(); androidConnector.InitShellJavaObject(); androidConnector.RequestPermission(); Debug.Log("TrueGear蓝牙初始化完成"); } public void StartRequestTrueGear() { TruegearAndroidConnector androidConnector = new TruegearAndroidConnector(); androidConnector.InitShellJavaObject(); androidConnector.RequestPermission(); Debug.Log("开始连接"); StartCoroutine(TrueGearAndroidConnector()); } public bool isGetConnect; private int isAvailableIndex = 0; private int GetConnectIndex; // 用于停止扫描和连接的标志 private bool shouldStopScan = false; private Coroutine scanCoroutine; /// /// 停止扫描和连接 /// public void StopScan() { shouldStopScan = true; if (scanCoroutine != null) { StopCoroutine(scanCoroutine); scanCoroutine = null; } Debug.Log("已停止TrueGear扫描和连接"); } /// /// 重置扫描状态(当用户选择设备时调用) /// public void ResetScanState() { shouldStopScan = false; isAvailableIndex = 20; GetConnectIndex = 20; } // 设备选择相关 public int SelectedDeviceIndex { get; set; } private List scannedDevices = new List(); /// /// 获取扫描到的设备列表 /// public List GetDeviceList() { TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance; if (androidConnector == null || !androidConnector.IsAvailable()) { return new List(); } scannedDevices = androidConnector.GetScanedDevices(); return scannedDevices; } /// /// 获取选中设备的地址 /// public string GetSelectedDeviceAddress() { if (scannedDevices != null && SelectedDeviceIndex >= 0 && SelectedDeviceIndex < scannedDevices.Count) { return scannedDevices[SelectedDeviceIndex].address; } return null; } /// /// 根据索引连接指定设备 /// public void ConnectToDeviceByIndex(int index) { if (scannedDevices == null || index < 0 || index >= scannedDevices.Count) { Debug.LogWarning("无效的设备索引"); return; } TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance; if (androidConnector == null || !androidConnector.IsAvailable()) { Debug.LogWarning("TrueGear 蓝牙不可用"); return; } DeviceData device = scannedDevices[index]; bool connected = androidConnector.ConnectToDevice(device.address); if (connected) { Debug.Log($"成功连接设备: {device.name} - {device.address}"); isGetConnect = true; SelectedDeviceIndex = index; ChangeElectricalLevel(); } else { Debug.LogWarning($"设备连接失败: {device.name} - {device.address}"); } } IEnumerator TrueGearAndroidConnector() { TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance; bool res = androidConnector.IsAvailable(); Debug.Log("蓝牙是否授权成功:"+res); while (!res&& isAvailableIndex>0) { yield return new WaitForSeconds(1f); Debug.Log("蓝牙尝试连接中...."); androidConnector.InitShellJavaObject(); androidConnector.RequestPermission(); res = androidConnector.IsAvailable(); isAvailableIndex--; } if (isAvailableIndex <= 0) { Debug.Log("蓝牙授权失败"); } else { Debug.Log("蓝牙授权成功"); StartScanTrueGear(); while (!isGetConnect&& GetConnectIndex>0) { GetScanedDevices(); StartConnect(); yield return new WaitForSeconds(1); Debug.Log("正在重新连接..."); GetConnectIndex--; } } } //搜索设备 public void StartScanTrueGear() { TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance; bool res = androidConnector.IsAvailable(); if (res) androidConnector.StartScan(); Debug.Log("OnStartScanClick" + res); } //获取设备列表 public void GetScanedDevices() { TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance; bool res = androidConnector.IsAvailable(); Debug.Log("OnGetScanedDevicesClick" + res); if (!res) return; List res1 = androidConnector.GetScanedDevices(); string str = ""; foreach (var item in res1) { str += (string.Format("{0}, {1} ", item.name, item.address)); } Debug.Log("OnGetScanedDevicesClick " + str); } //开始连接设备 public void StartConnect() { TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance; bool res = androidConnector.IsAvailable(); Debug.Log("OnStartConnectClick" + res); if (!res) return; List devices = androidConnector.GetScanedDevices(); if (devices == null || devices.Count == 0) { Debug.Log("未扫描到任何设备"); return; } foreach (var device in devices) { bool connected = androidConnector.ConnectToDevice(device.address); if (connected) { Debug.Log($"成功连接设备: {device.name} - {device.address}"); isGetConnect = true; ChangeElectricalLevel(); return; } else { Debug.LogWarning($"设备被占用或连接失败: {device.name} - {device.address}"); } } Debug.Log("No device found"); } public void ChangeElectricalLevel() { TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance; bool isZD= androidConnector.ModifyElectricalPercent(80); Debug.LogError("是否震动:"+isZD); } /// /// 断开连接 /// public void CloseConnect() { TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance; androidConnector.DisconnectFromDevice(); } private void OnApplicationQuit() { //断开连接 Debug.Log("断开连接"); #if !UNITY_EDITOR CloseConnect(); #endif } /// /// 触发TrueGear震动 /// /// 效果名,可自定义 /// 作用的电机ID列表 /// 起始时间,单位ms /// 结束时间,单位ms /// 起始强度(0-100) /// 结束强度(0-100) /// 强度模式:Const/Fade/FadeInAndOut /// 震动位置 public void PlayVibrationEffect( string effectName, List motorIndex, int startTime = 0, int endTime = 300, int startIntensity = 30, int endIntensity = 30, string intensityMode = "Const", string actionType="Shake" ) { string indexStr = string.Join(",", motorIndex); Debug.Log(indexStr); string json = $@" {{ ""name"":""{effectName}"", ""uuid"":""{effectName}"", ""keep"":""False"", ""priority"": 0, ""tracks"":[ {{ ""start_time"":{startTime}, ""end_time"":{endTime}, ""stop_name"":"""", ""start_intensity"":{startIntensity}, ""end_intensity"":{endIntensity}, ""intensity_mode"":""{intensityMode}"", ""action_type"":""{actionType}"", ""once"":""True"", ""interval"":1, ""index"":[{indexStr}] }} ] }}"; SendPlayEffectByContent(json); } public void SendPlayEffectByContent(string jsonStr) { TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance; bool res = androidConnector.IsAvailable(); Debug.Log("OnTestClick" + res); if (!res) return; try { androidConnector.SendPlayEffectByContent(jsonStr); } catch (Exception ex) { Debug.LogError("调用 TrueGear 崩溃保护: " + ex); ReconnectTrueGear(); } } // 当检测蓝牙断开或异常时调用 void ReconnectTrueGear() { try { var conn = TruegearAndroidConnector.Instance; conn.InitShellJavaObject(); conn.RequestPermission(); conn.StartScan(); } catch (Exception e) { Debug.LogError("重新初始化 TrueGear 失败:" + e); } } public List hitParts=new List(); public void AddHitPart() { hitParts.Add("leftUp"); hitParts.Add("leftDown"); hitParts.Add("rightUp"); hitParts.Add("rightDown"); hitParts.Add("rightAim"); } public void OnHit(bool isUp, int index,bool isArm) { // 如果未启用马甲功能,则跳过 if (!enableTrueGear) { return; } TruegearAndroidConnector androidConnector = TruegearAndroidConnector.Instance; if (androidConnector == null) { Debug.LogWarning("TrueGear connector 为空,跳过调用"); isGetConnect = false; return; } if (!androidConnector.IsAvailable()) { Debug.LogWarning("TrueGear 蓝牙不可用或断开,跳过调用"); isGetConnect = false; return; } if (!isGetConnect) { // 不再自动连接,只记录状态 Debug.LogWarning("TrueGear 未连接,跳过震动"); return; } List motorIDs = new List(); string hitPart= hitParts[index]; switch (hitPart) { case "leftUp": motorIDs.AddRange( isUp?new int[] { 0, 1, 4,5 }: new int[] { 100, 101, 104,105 }); break; case "leftDown": motorIDs.AddRange(isUp?new int[] { 8, 9, 12,13 }: new int[] { 108, 109, 112,113 }); break; case "rightUp": motorIDs.AddRange(isUp?new int[] { 2,3,6,7}: new int[] { 102, 103, 106,107 }); break; case "rightDown": motorIDs.AddRange(isUp?new int[] { 10,11,14,15}: new int[] { 114, 115, 118,119 }); break; case "rightAim": motorIDs.AddRange(new int[] { 0,100}); break; default: motorIDs.Add(0); break; } PlayVibrationEffect( effectName: $"Hit_{hitPart}", motorIndex: motorIDs, startIntensity: isArm?20:50, endIntensity: isArm?20:50, endTime: 400, actionType: isArm? "Electrical" :"Shake" ); } }