using System; using System.Collections; using System.Collections.Generic; using Lofelt.NiceVibrations; using UnityEngine; namespace OCES.Haptic { public class HapticSystem : MonoBehaviour { public static HapticSystem Instance {get; private set;} [NonSerialized] public bool IsHapticSupported = DeviceCapabilities.isVersionSupported; [NonSerialized] public bool IsMeetsAdvanceRequirements = DeviceCapabilities.meetsAdvancedRequirements; HapticObjectConfig m_hapticObjects; const string k_hapticConfigPath = "HapticData/"; const string k_hapticResourcesPath = "Haptics/"; public void Play(uint hapticId, bool isDirectCall = true) { HapticObject hapticObject = this.m_hapticObjects.QueryById(hapticId); if (hapticObject != null) { Play(hapticObject); if (isDirectCall) { Debug.LogWarning($"[Haptic System] Playing haptic id {hapticId} without play audio." + "This method should only be called during debugging."); } } else { Debug.LogError("[Haptic System] Could not find Haptic Object with id: " + hapticId); } } public void Play(HapticObject hapticObject) { switch (hapticObject.Type) { case HapticType.Preset: if (Enum.TryParse(hapticObject.Payload, out HapticPatterns.PresetType hapticPattern)) { HapticPatterns.PlayPreset(hapticPattern); } else { Debug.LogError($"[Haptic System] Could not parse haptic pattern: {hapticObject.Payload}]"); } break; case HapticType.Emphasis: if (hapticObject.Amplitude < 0f || hapticObject.Frequency < 0f) { Debug.LogWarning($"[Haptic System] Haptic {hapticObject.Id} have no amplitude or frequency." + "Please check the datatable."); break; } HapticPatterns.PlayEmphasis(hapticObject.Amplitude, hapticObject.Frequency); break; case HapticType.Constant: if (hapticObject.Amplitude < 0f || hapticObject.Frequency < 0f || hapticObject.Duration < 0f) { Debug.LogWarning($"[Haptic System] Haptic {hapticObject.Id} have no amplitude, frequency or duration." + "Please check the datatable."); break; } HapticController.Stop(); HapticPatterns.PlayConstant(hapticObject.Amplitude, hapticObject.Frequency, hapticObject.Duration); break; case HapticType.Advance: if (Enum.TryParse(hapticObject.FallbackPreset, out HapticPatterns.PresetType fallbackPreset)) { HapticController.fallbackPreset = fallbackPreset; HapticClip hapticClip = GetHapticClip(hapticObject); if (hapticClip) { HapticController.Stop(); HapticController.Play(hapticClip); } else { Debug.LogError($"[Haptic System] Could not parse haptic file: {hapticObject.Payload}"); } } else { Debug.LogError($"[Haptic System] Could not parse fallback preset: {hapticObject.FallbackPreset}]"); } break; default: throw new ArgumentOutOfRangeException(); } } public void Stop() { HapticController.Stop(); } void Awake() { if (Instance && Instance != this) { Destroy(gameObject); return; } Instance = this; DontDestroyOnLoad(gameObject); this.m_hapticObjects = HapticConfigLoader.Load(k_hapticConfigPath + "HapticObject"); } static HapticClip GetHapticClip(HapticObject hapticObject) { return Resources.Load(k_hapticResourcesPath + hapticObject.Payload); } static class HapticConfigLoader { internal static T Load(string tableName) where T : IBinarySerializable, new() { TextAsset bytes = Resources.Load(tableName); if (!bytes) Debug.LogError($"未找到表 {tableName}"); IBinarySerializable data = new T(); bool readOk = FileManager.ReadBinaryDataFromBytes(bytes.bytes, ref data); if (readOk) return (T)data; Debug.LogError($"{tableName} 解析出错,类型 {typeof(T)}"); return default; } } } }