feat: Import Haptic System
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12705f55004c045a2ae82b5407a3cbbb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* auto generated by tools(注意:千万不要手动修改本文件)
|
||||
* HapticObject
|
||||
*/
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OCES.Haptic
|
||||
{
|
||||
[Serializable]
|
||||
public partial class HapticObject : IBinarySerializable
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public uint Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 类型
|
||||
/// </summary>
|
||||
public HapticType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 强度
|
||||
/// </summary>
|
||||
public float Amplitude { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 尖锐度
|
||||
/// </summary>
|
||||
public float Frequency { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 时长
|
||||
/// </summary>
|
||||
public float Duration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 播放来源
|
||||
/// </summary>
|
||||
public string Payload { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 回退预设
|
||||
/// </summary>
|
||||
public string FallbackPreset { get; set; }
|
||||
|
||||
|
||||
public void DeSerialize(BinaryReader reader)
|
||||
{
|
||||
Id = reader.ReadUInt32();
|
||||
Type = (HapticType)reader.ReadByte();
|
||||
Amplitude = reader.ReadSingle();
|
||||
Frequency = reader.ReadSingle();
|
||||
Duration = reader.ReadSingle();
|
||||
Payload = reader.ReadString();
|
||||
FallbackPreset = reader.ReadString();
|
||||
}
|
||||
|
||||
public void Serialize(BinaryWriter writer)
|
||||
{
|
||||
writer.Write(Id);
|
||||
writer.Write((byte)Type);
|
||||
writer.Write(Amplitude);
|
||||
writer.Write(Frequency);
|
||||
writer.Write(Duration);
|
||||
writer.Write(Payload);
|
||||
writer.Write(FallbackPreset);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public partial class HapticObjectConfig : IBinarySerializable
|
||||
{
|
||||
Dictionary<uint,HapticObject> m_hapticObjectInfos = new();
|
||||
List<HapticObject> m_hapticObjectInfoList;
|
||||
|
||||
public List<HapticObject> HapticObjectList()
|
||||
{
|
||||
this.m_hapticObjectInfoList ??= new List<HapticObject>(this.m_hapticObjectInfos.Values);
|
||||
return this.m_hapticObjectInfoList;
|
||||
}
|
||||
|
||||
public void DeSerialize(BinaryReader reader)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
HapticObject tempData = new();
|
||||
tempData.DeSerialize(reader);
|
||||
this.m_hapticObjectInfos.Add(tempData.Id, tempData);
|
||||
}
|
||||
}
|
||||
|
||||
public void Serialize(BinaryWriter writer)
|
||||
{
|
||||
writer.Write(this.m_hapticObjectInfos.Count);
|
||||
foreach (HapticObject hapticObject in this.m_hapticObjectInfos.Values)
|
||||
{
|
||||
hapticObject.Serialize(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public HapticObject QueryById(uint id)
|
||||
{
|
||||
return this.m_hapticObjectInfos.GetValueOrDefault(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57a231d8d4f5a433caa1316cd9b055ae
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e1d12770ca114030b35c14f8c72b193
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.IO;
|
||||
|
||||
namespace OCES.Haptic
|
||||
{
|
||||
public interface IBinarySerializable
|
||||
{
|
||||
void DeSerialize(BinaryReader reader);
|
||||
void Serialize(BinaryWriter writer);
|
||||
}
|
||||
|
||||
public enum HapticType
|
||||
{
|
||||
Preset = 0, //播放预制
|
||||
Emphasis = 1, //播放瞬时
|
||||
Constant = 2, //播放连续
|
||||
Advance = 3, //播放文件
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件操作类
|
||||
/// </summary>
|
||||
public static class FileManager
|
||||
{
|
||||
/// <summary>
|
||||
/// 从内存流中读取二进制
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public static bool ReadBinaryDataFromBytes(byte[] bytes, ref IBinarySerializable data)
|
||||
{
|
||||
if (bytes == null)
|
||||
return false;
|
||||
using (MemoryStream memoryStream = new(bytes))
|
||||
{
|
||||
using (var br = new BinaryReader(memoryStream))
|
||||
{
|
||||
data.DeSerialize(br);
|
||||
br.Close();
|
||||
}
|
||||
memoryStream.Close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7267d262bcf45e0ba1855dccdc5e87e
|
||||
timeCreated: 1775705326
|
||||
@@ -0,0 +1,138 @@
|
||||
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<HapticObjectConfig>(k_hapticConfigPath + "HapticObject");
|
||||
}
|
||||
|
||||
static HapticClip GetHapticClip(HapticObject hapticObject)
|
||||
{
|
||||
return Resources.Load<HapticClip>(k_hapticResourcesPath + hapticObject.Payload);
|
||||
}
|
||||
|
||||
static class HapticConfigLoader
|
||||
{
|
||||
internal static T Load<T>(string tableName) where T : IBinarySerializable, new()
|
||||
{
|
||||
TextAsset bytes = Resources.Load<TextAsset>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1939bb20b5db46c1a5f7354ca0fba87
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user