Merge branch 'main' into feature/HapticSystem

This commit is contained in:
2026-04-13 17:31:59 +08:00
11 changed files with 134 additions and 62 deletions
@@ -1,6 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 3f3b3e40c5ec34183af765f15c1ce362 guid: 3f3b3e40c5ec34183af765f15c1ce362
folderAsset: yes
PluginImporter: PluginImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
@@ -12,24 +11,6 @@ PluginImporter:
isExplicitlyReferenced: 0 isExplicitlyReferenced: 0
validateReferences: 1 validateReferences: 1
platformData: platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 0
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first: - first:
Any: Any:
second: second:
@@ -40,42 +21,13 @@ PluginImporter:
second: second:
enabled: 0 enabled: 0
settings: settings:
CPU: AnyCPU
DefaultValueInitialized: true DefaultValueInitialized: true
OS: AnyOS
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
- first: - first:
iPhone: iOS iPhone: iOS
second: second:
enabled: 1 enabled: 1
settings: settings:
AddToEmbeddedBinaries: true AddToEmbeddedBinaries: true
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: e640dc3c900064126804112a521170ea
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: be8f215dba3904ddf9f72fc064c97e71
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
+15 -3
View File
@@ -1012,7 +1012,7 @@ GameObject:
- component: {fileID: 1394234350} - component: {fileID: 1394234350}
- component: {fileID: 1394234349} - component: {fileID: 1394234349}
m_Layer: 5 m_Layer: 5
m_Name: Button (Legacy) m_Name: PlaySound
m_TagString: Untagged m_TagString: Untagged
m_Icon: {fileID: 0} m_Icon: {fileID: 0}
m_NavMeshLayer: 0 m_NavMeshLayer: 0
@@ -1085,15 +1085,27 @@ MonoBehaviour:
- m_Target: {fileID: 2093584670} - m_Target: {fileID: 2093584670}
m_TargetAssemblyTypeName: OCES.Audio.AudioSystem, Assembly-CSharp m_TargetAssemblyTypeName: OCES.Audio.AudioSystem, Assembly-CSharp
m_MethodName: Play m_MethodName: Play
m_Mode: 5 m_Mode: 3
m_Arguments: m_Arguments:
m_ObjectArgument: {fileID: 0} m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 11 m_IntArgument: 57
m_FloatArgument: 0 m_FloatArgument: 0
m_StringArgument: rain m_StringArgument: rain
m_BoolArgument: 0 m_BoolArgument: 0
m_CallState: 2 m_CallState: 2
- m_Target: {fileID: 2093584670}
m_TargetAssemblyTypeName: OCES.Audio.AudioSystem, Assembly-CSharp
m_MethodName: Play
m_Mode: 3
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 58
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!114 &1394234350 --- !u!114 &1394234350
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -130,6 +130,11 @@ public partial class AudioObject : IBinarySerializable
/// </summary> /// </summary>
public bool RandomType { get; set; } public bool RandomType { get; set; }
/// <summary>
/// Volume Step阈值 ms
/// </summary>
public uint VolumeStepThreshold { get; set; }
/// <summary> /// <summary>
/// 起始音量 /// 起始音量
/// dB /// dB
@@ -178,6 +183,7 @@ public partial class AudioObject : IBinarySerializable
BlendCrossFadeType = (BlendCrossFadeType)reader.ReadByte(); BlendCrossFadeType = (BlendCrossFadeType)reader.ReadByte();
LimitRepetition = reader.ReadByte(); LimitRepetition = reader.ReadByte();
RandomType = reader.ReadBoolean(); RandomType = reader.ReadBoolean();
VolumeStepThreshold = reader.ReadUInt32();
Volume = reader.ReadInt32(); Volume = reader.ReadInt32();
VolumeStep = reader.ReadInt32(); VolumeStep = reader.ReadInt32();
} }
@@ -216,6 +222,7 @@ public partial class AudioObject : IBinarySerializable
writer.Write((byte)BlendCrossFadeType); writer.Write((byte)BlendCrossFadeType);
writer.Write(LimitRepetition); writer.Write(LimitRepetition);
writer.Write(RandomType); writer.Write(RandomType);
writer.Write(VolumeStepThreshold);
writer.Write(Volume); writer.Write(Volume);
writer.Write(VolumeStep); writer.Write(VolumeStep);
} }
@@ -71,6 +71,8 @@ public static class AudioObjectDefinitions
{ "Grid", 54 }, { "Grid", 54 },
{ "NVDice", 55 }, { "NVDice", 55 },
{ "NVHeartbeats", 56 }, { "NVHeartbeats", 56 },
{ "au_sfx_notice_level_countDown_edge", 57 },
{ "au_sfx_notice_level_countDown_time", 58 },
{ "sfx_amb_desert", 2000 }, { "sfx_amb_desert", 2000 },
{ "sfx_amb_forest", 2001 }, { "sfx_amb_forest", 2001 },
{ "sfx_anim_common_item_fly", 3000 }, { "sfx_anim_common_item_fly", 3000 },
@@ -2,6 +2,7 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OCES.Audio.HandWritten;
using UnityEngine; using UnityEngine;
using UnityEngine.Audio; using UnityEngine.Audio;
@@ -33,6 +34,7 @@ namespace OCES.Audio
AudioSourcePool m_pool; AudioSourcePool m_pool;
AudioContainerSelector m_containerSelector; AudioContainerSelector m_containerSelector;
PitchStepResolver m_pitchStepResolver; PitchStepResolver m_pitchStepResolver;
VolumeStepResolver m_volumeStepResolver;
#if UNITY_EDITOR #if UNITY_EDITOR
void Update() void Update()
@@ -74,6 +76,7 @@ namespace OCES.Audio
this.m_pool = pool; this.m_pool = pool;
this.m_containerSelector = new AudioContainerSelector(); this.m_containerSelector = new AudioContainerSelector();
this.m_pitchStepResolver = new PitchStepResolver(); this.m_pitchStepResolver = new PitchStepResolver();
this.m_volumeStepResolver = new VolumeStepResolver();
AudioMixerGroup[] sfx = Find("Master/Regular/SFX"); AudioMixerGroup[] sfx = Find("Master/Regular/SFX");
if (sfx.Length > 0) this.m_sfxGroup = sfx[0]; if (sfx.Length > 0) this.m_sfxGroup = sfx[0];
@@ -173,7 +176,8 @@ namespace OCES.Audio
// 执行播放 // 执行播放
float pitch = this.m_pitchStepResolver.ResolvePitch(audioObject, now); //算一下用不用变调 float pitch = this.m_pitchStepResolver.ResolvePitch(audioObject, now); //算一下用不用变调
PlayNewSound(audioObject, pitch); float volume = this.m_volumeStepResolver.ResolveVolume(audioObject, now);
PlayNewSound(audioObject, pitch, volume);
this.m_lastPlayTime[audioObject.Id] = now; this.m_lastPlayTime[audioObject.Id] = now;
onPlay?.Invoke(); onPlay?.Invoke();
} }
@@ -182,12 +186,13 @@ namespace OCES.Audio
// 播放逻辑 // 播放逻辑
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
void PlayNewSound(AudioObject audioObject, float pitch) void PlayNewSound(AudioObject audioObject, float pitch, float volume)
{ {
ActiveSound active = new() ActiveSound active = new()
{ {
AudioObject = audioObject, AudioObject = audioObject,
Pitch = pitch, Pitch = pitch,
Volume = volume,
State = ActiveSoundState.Pending, State = ActiveSoundState.Pending,
StartTime = Time.realtimeSinceStartupAsDouble, StartTime = Time.realtimeSinceStartupAsDouble,
}; };
@@ -207,7 +212,7 @@ namespace OCES.Audio
/// <summary> /// <summary>
/// 连续容器播放协程(Random / Sequence 持续模式) /// 连续容器播放协程(Random / Sequence 持续模式)
/// </summary> /// </summary>
IEnumerator PlayContainerContinuous(AudioSource source, AudioObject audioObject, ActiveSound chainActive, int startIndex, float pitch) IEnumerator PlayContainerContinuous(AudioSource source, AudioObject audioObject, ActiveSound chainActive, int startIndex)
{ {
bool isRandom = audioObject.ContainerType == ContainerType.Random; bool isRandom = audioObject.ContainerType == ContainerType.Random;
@@ -229,7 +234,7 @@ namespace OCES.Audio
limitRepetition); limitRepetition);
// 配置并播放 // 配置并播放
if (!SetupSource(source, audioObject, pitch, index)) if (!SetupSource(source, chainActive, index))
{ {
Debug.LogError($"音频文件未找到:{audioObject.Name[index]}"); Debug.LogError($"音频文件未找到:{audioObject.Name[index]}");
yield break; yield break;
@@ -334,8 +339,9 @@ namespace OCES.Audio
return this.m_sfxGroup; return this.m_sfxGroup;
} }
bool SetupSource(AudioSource source, AudioObject audioObject, float pitch, int clipIndex = 0) bool SetupSource(AudioSource source, ActiveSound activeSound, int clipIndex = 0)
{ {
AudioObject audioObject = activeSound.AudioObject;
AudioClip clip = Resources.Load<AudioClip>($"Audios/{audioObject.Name[clipIndex]}"); // TODO 抽象同一资源加载接口 AudioClip clip = Resources.Load<AudioClip>($"Audios/{audioObject.Name[clipIndex]}"); // TODO 抽象同一资源加载接口
if (!clip) if (!clip)
{ {
@@ -347,7 +353,8 @@ namespace OCES.Audio
source.loop = audioObject.LoopCount < 0; source.loop = audioObject.LoopCount < 0;
source.priority = audioObject.Priority; source.priority = audioObject.Priority;
source.outputAudioMixerGroup = GetMixerGroup(audioObject.MixingType); source.outputAudioMixerGroup = GetMixerGroup(audioObject.MixingType);
source.pitch = pitch; source.pitch = activeSound.Pitch;
source.volume = activeSound.Volume;
return true; return true;
} }
@@ -371,6 +378,7 @@ namespace OCES.Audio
{ {
AudioObject audioObject = active.AudioObject; AudioObject audioObject = active.AudioObject;
float pitch = active.Pitch; float pitch = active.Pitch;
float volume = active.Volume;
// ======================= // =======================
// Blend(每个clip一个ActiveSound // Blend(每个clip一个ActiveSound
@@ -385,10 +393,11 @@ namespace OCES.Audio
{ {
AudioObject = audioObject, AudioObject = audioObject,
Pitch = pitch, Pitch = pitch,
State = ActiveSoundState.Playing Volume = volume,
State = ActiveSoundState.Playing,
}; };
if (!SetupSource(source, audioObject, pitch, i)) if (!SetupSource(source, child, i))
{ {
this.m_pool.ReturnToPool(source.gameObject); this.m_pool.ReturnToPool(source.gameObject);
continue; continue;
@@ -424,7 +433,7 @@ namespace OCES.Audio
int start = audioObject.ContainerType == ContainerType.Random ? -1 : 0; int start = audioObject.ContainerType == ContainerType.Random ? -1 : 0;
active.Coroutine = StartCoroutine( active.Coroutine = StartCoroutine(
PlayContainerContinuous(sourceSingle, audioObject, active, start, pitch) PlayContainerContinuous(sourceSingle, audioObject, active, start)
); );
return; return;
@@ -440,9 +449,9 @@ namespace OCES.Audio
_ => 0 _ => 0
}; };
if (!SetupSource(sourceSingle, audioObject, pitch, index)) if (!SetupSource(sourceSingle, active, index))
{ {
m_pool.ReturnToPool(sourceSingle.gameObject); this.m_pool.ReturnToPool(sourceSingle.gameObject);
return; return;
} }
@@ -506,6 +515,7 @@ namespace OCES.Audio
public int CurrentLoopCount; public int CurrentLoopCount;
public Coroutine Coroutine; public Coroutine Coroutine;
public float Pitch; public float Pitch;
public float Volume;
public ActiveSoundState State; public ActiveSoundState State;
} }
} }
@@ -0,0 +1,40 @@
using System.Collections.Generic;
using UnityEngine;
namespace OCES.Audio.HandWritten
{
public class VolumeStepResolver
{
readonly Dictionary<uint, int> m_volumeStepCounts = new();
readonly Dictionary<uint, double> m_volumeStepLastTime = new();
internal float ResolveVolume(AudioObject audioObject, double time)
{
// 计算一下配置的音量是多少
float baseVolume = Mathf.Pow(10,audioObject.Volume / 20f);
// 优化版。看看表现,要是确实Mathf.Pow造成性能卡点了就用这个。
//float baseVolume = audioObject.Volume == 0 ? 1f : Mathf.Pow(10,audioObject.Volume / 20f);
if (audioObject.VolumeStepThreshold == 0) //没配置VolumeStep
{
return baseVolume;
}
// 超时了,或者没播过
if (!this.m_volumeStepLastTime.TryGetValue(audioObject.Id, out double lastVolumeStepTime)
|| time - lastVolumeStepTime > audioObject.VolumeStepThreshold)
{
this.m_volumeStepCounts[audioObject.Id] = 0;
this.m_volumeStepLastTime[audioObject.Id] = time;
return baseVolume;
}
//命中了
int volumeStepCount = this.m_volumeStepCounts[audioObject.Id];
volumeStepCount = this.m_volumeStepCounts[audioObject.Id] = volumeStepCount + 1;
this.m_volumeStepLastTime[audioObject.Id] = time;
return Mathf.Clamp(Mathf.Pow(10, (audioObject.Volume + audioObject.VolumeStep * volumeStepCount) / 20f), 0f, 1f);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0059d6fc851c474a97bc05f6385f9a48
timeCreated: 1776067889