Compare commits

...

10 Commits

Author SHA1 Message Date
Oliver 933bc4ceb0 fix: AudioImportTool NPE when run outside Play mode
Replace AudioExtendSettings.Instance with local AssetDatabase-loaded field to avoid nullref when AudioSystem hasn't yet initialized.
2026-06-05 11:59:25 +08:00
Oliver faba10b33e 更新说明 2026-06-04 19:10:50 +08:00
Oliver 9d34a8b556 增加测试文件,修改buffer size解决淡变时会爆音的问题 2026-05-28 19:50:58 +08:00
Oliver 25919b3f79 Update binary data. 2026-05-26 10:12:29 +08:00
Oliver 0fa6236211 chore: comment out debug log 2026-05-26 10:12:10 +08:00
Oliver a46b450ef0 feat: 音效、音量、触感开关控制 2026-05-22 20:40:35 +08:00
Oliver 5ceffa4d61 closed: streaming support 2026-05-19 12:07:48 +08:00
Oliver 106256cc32 关掉节拍器 2026-05-19 12:07:21 +08:00
Oliver 005af5c2b8 update: Playersettings 2026-05-19 12:07:13 +08:00
Oliver 9dc4228b5c feat: 在Unity内支持直接调整音频文件进行混音 2026-05-19 12:04:31 +08:00
64 changed files with 327 additions and 126 deletions
+19
View File
@@ -170,6 +170,25 @@ SfxSystem manages: throttle (`ThrottleCount`), min interval (`MinInterval`), pri
- `HapticSystem.Instance.Stop(uint? hapticId = null)` — stops current haptic playback
- Supports four `HapticType`s: `Preset`, `Emphasis`, `Constant`, `Advance` (`.haptic` file)
#### Device capability & fallback
`HapticController.Play()` (`Lofelt/.../HapticController.cs:350`) uses a three-tier decision chain:
1. **Advanced device** (`DeviceCapabilities.meetsAdvancedRequirements`) → full `.haptic` playback via `LofeltHaptics`
2. **Gamepad** (`GamepadRumbler.CanPlay()`) → gamepad rumble
3. **Basic OS support** (`DeviceCapabilities.isVersionSupported`) → **always falls back to a Preset**
4. None of above → silent no-op
**Advance (`.haptic` file) fallback is Preset-only** — it never degrades to Emphasis or Constant. The fallback Preset is configured via `HapticObject.FallbackPreset` in the data table.
| HapticType | Advanced | Android basic | iOS basic |
|------------|----------|---------------|-----------|
| **Advance** | Full `.haptic` | → Preset | → Preset |
| **Emphasis** | JSON clip | 50ms max-amplitude pulse | → amplitude-mapped Preset |
| **Constant** | JSON clip with modulation | max-amplitude for `duration` | → hardcoded `HeavyImpact` |
Emphasis and Constant have their own internal fallback chains (template-based JSON clips on advanced, raw motor patterns or Presets on basic), but these are independent direct-invoke paths — they are never used as fallback targets for Advance.
---
## Interactive Music System
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -7,9 +7,9 @@ AudioImporter:
serializedVersion: 2
loadType: 2
sampleRateSetting: 2
sampleRateOverride: 44100
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.13
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
+2 -2
View File
@@ -7,9 +7,9 @@ AudioImporter:
serializedVersion: 2
loadType: 2
sampleRateSetting: 2
sampleRateOverride: 44100
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.13
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
+2 -2
View File
@@ -7,9 +7,9 @@ AudioImporter:
serializedVersion: 2
loadType: 2
sampleRateSetting: 2
sampleRateOverride: 44100
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.13
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
+2 -2
View File
@@ -7,9 +7,9 @@ AudioImporter:
serializedVersion: 2
loadType: 2
sampleRateSetting: 2
sampleRateOverride: 44100
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.13
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
+7
View File
@@ -249,8 +249,14 @@ AudioMixerController:
m_EnableSuspend: 1
m_UpdateMode: 0
m_ExposedParameters:
- guid: d66e5a701962f484baca61ea5f29bab9
name: MusicVolume
- guid: 9b4461d5598de4602b001fc9d34f76a7
name: LowpassFreq
- guid: f9b2498f18d9c4346b50d00374df58fc
name: SFXVolume
- guid: 15cd4cd29b1a64dacb39ca2eda4de378
name: SFXAccentVolume
m_AudioMixerGroupViews:
- guids:
- 3ef0a681afabf403eae42ddfe3bed37e
@@ -319,6 +325,7 @@ AudioMixerSnapshotController:
676d0e59581a446dfb975928b4b3a4ea: 22000
0053647b950eb4d8abf883dc07d6b4ef: 1
47b8a12e60a1c4cf18d0d0c28f12866d: 440
f9b2498f18d9c4346b50d00374df58fc: 0
c31161cf8dc3a48478fe71156b990b48: 1333
d171c8cff3d664001b51b62c1b77ab53: 0
m_TransitionOverrides: {}
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -11,7 +11,7 @@ AudioImporter:
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
Binary file not shown.
+1 -1
View File
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: c5826c32750024cf0a317c781cbd9c49
guid: e1e3771c46788490d96beed6956a6c03
AudioImporter:
externalObjects: {}
serializedVersion: 7
Binary file not shown.
+1 -1
View File
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 0279ce4eacbbf45d0b332f1996c7715c
guid: 49b7f87b4607c4005aa6739e4a777f60
AudioImporter:
externalObjects: {}
serializedVersion: 7
@@ -6,10 +6,10 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
@@ -6,12 +6,12 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -6,12 +6,12 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -6,12 +6,12 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -6,10 +6,10 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
@@ -6,10 +6,10 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
@@ -6,10 +6,10 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
@@ -6,12 +6,12 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -6,10 +6,10 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
@@ -6,12 +6,12 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -6,12 +6,12 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -6,12 +6,12 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -6,12 +6,12 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -6,12 +6,12 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -6,12 +6,12 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
@@ -6,10 +6,10 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
@@ -6,10 +6,10 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
@@ -6,10 +6,10 @@ AudioImporter:
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
+1 -1
View File
@@ -971,7 +971,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!114 &660842743
MonoBehaviour:
m_ObjectHideFlags: 0
@@ -0,0 +1,52 @@
using UnityEditor.Build;
using UnityEditor;
using System.IO;
using UnityEditor.Build.Reporting;
using UnityEngine;
namespace OCES.Editor
{
#if false
public class CopyWavesForMixing : IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
public int callbackOrder
{
get { return 0; }
}
static string _audioStreamingPath;
public void OnPreprocessBuild(BuildReport report)
{
const string guid = "de80878c933394e2da0966a1466fd793";
Audio.AudioExtendSettings audioSettings =
AssetDatabase.LoadAssetAtPath<Audio.AudioExtendSettings>(AssetDatabase.GUIDToAssetPath(guid));
string audioPath = Path.Combine("Assets", "Resources",audioSettings.audioResourcePath);
DirectoryInfo directoryInfo = new(audioPath);
_audioStreamingPath = Path.Combine(Application.streamingAssetsPath, "Audios");
if (Directory.Exists(_audioStreamingPath)) Directory.Delete(_audioStreamingPath, true);
Directory.CreateDirectory(_audioStreamingPath);
foreach (FileInfo file in directoryInfo.GetFiles())
{
if (file.Extension is ".wav" or ".mp3")
{
file.CopyTo(Path.Combine(_audioStreamingPath, file.Name), true);
}
}
Debug.Log(_audioStreamingPath);
}
public void OnPostprocessBuild(BuildReport report)
{
if (Directory.Exists(_audioStreamingPath)) Directory.Delete(_audioStreamingPath, true);
}
}
#endif
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e2d7bb1448fb4a7897840c63d350e597
timeCreated: 1779103933
@@ -21,10 +21,13 @@ namespace OCES
[CanBeNull]
internal T LoadSync<T>(string path) where T : Object
{
#if !AUDIO_MIXING
if (this.m_cachedObjects.TryGetValue(path, out Object cachedObject))
{
return cachedObject as T;
}
#endif
T newObject;
if (this.m_assetProvider is not null)
@@ -36,8 +39,10 @@ namespace OCES
newObject = Resources.Load<T>(path);
Debug.LogWarning($"[ResourceLoader] No IAssetProvider set, falling back to Resources.Load for '{path}'");
}
#if !AUDIO_MIXING
this.m_cachedObjects.Add(path, newObject);
#endif
return newObject;
}
@@ -23,11 +23,10 @@ namespace OCES
{
if (typeof(T) != typeof(AudioClip))
{
Debug.LogError($"[StreamingAssetProvider] Load<{typeof(T).Name}> 不支持,仅支持 AudioClip");
return null;
return Resources.Load<T>(path);
}
string fullPath = Path.Combine(Application.streamingAssetsPath, path);
string fullPath = Path.Combine("Audios", Application.streamingAssetsPath, path) + ".wav";
if (!File.Exists(fullPath))
{
Debug.LogError($"[StreamingAssetProvider] 文件 {fullPath} 不存在。");
@@ -48,25 +47,26 @@ namespace OCES
{
if (typeof(T) != typeof(AudioClip))
{
Debug.LogError($"[StreamingAssetProvider] LoadAsync<{typeof(T).Name}> 不支持,仅支持 AudioClip");
onComplete?.Invoke(null);
ResourceRequest resourceRequest = Resources.LoadAsync<T>(path);
yield return resourceRequest;
onComplete?.Invoke(resourceRequest.asset as T);
yield break;
}
string fullPath = Path.Combine(Application.streamingAssetsPath, path);
string fullPath = Path.Combine("Audios", Application.streamingAssetsPath, path);
string url = "file://" + fullPath;
using UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.WAV);
yield return request.SendWebRequest();
using UnityWebRequest webRequest = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.WAV);
yield return webRequest.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
if (webRequest.result == UnityWebRequest.Result.Success)
{
AudioClip clip = DownloadHandlerAudioClip.GetContent(request);
AudioClip clip = DownloadHandlerAudioClip.GetContent(webRequest);
onComplete?.Invoke(clip as T);
}
else
{
Debug.LogError($"[StreamingAssetProvider] 加载失败: {url}, 错误: {request.error}");
Debug.LogError($"[StreamingAssetProvider] 加载失败: {url}, 错误: {webRequest.error}");
onComplete?.Invoke(null);
}
}
@@ -127,6 +127,27 @@ namespace OCES.Audio
).SetEase(Ease.OutCubic);
}
public void SetMusicVolume(float targetVolume)
{
this.m_mixer.SetFloat("MusicVolume", targetVolume);
}
public void SetSFXVolume(float targetVolume)
{
this.m_mixer.SetFloat("SFXVolume", targetVolume);
this.m_mixer.SetFloat("SFXAccentVolume", targetVolume);
}
public void SetMusicState(bool enable)
{
SetMusicVolume(enable ? 0 : -80);
}
public void SetSFXState(bool enable)
{
SetSFXVolume(enable ? 0 : -80);
}
/// <summary>
/// 更新游戏状态,驱动音乐与环境音系统切换。
/// 调用示例:AudioSystem.Instance.SetState(GameState.Game);
@@ -9,9 +9,26 @@ namespace OCES.Audio
public static class AudioImportTool
{
static AudioExtendSettings s_settings;
static AudioExtendSettings Settings
{
get
{
if (s_settings == null)
{
s_settings = AssetDatabase.LoadAssetAtPath<AudioExtendSettings>(
"Assets/Settings/AudioExtendSettings.asset");
if (s_settings == null)
Debug.LogError("[AudioImportTool] 无法加载 AudioExtendSettings.asset,请确保资产存在于 Assets/Settings/ 目录");
}
return s_settings;
}
}
static string ConfigAbsolutePath
{
get { return Path.Combine(Application.dataPath, "Resources", AudioExtendSettings.Instance.audioConfigPath); }
get { return Path.Combine(Application.dataPath, "Resources", Settings.audioConfigPath); }
}
[MenuItem("Tools/OCES/Audio/Apply Audio Import Settings")]
@@ -19,7 +36,7 @@ namespace OCES.Audio
{
if (EditorUtility.DisplayDialog(
"Apply Audio Import Settings",
$"将对 {AudioExtendSettings.Instance.FullAudioResourcePath} 下所有文件重新应用导入设置,确认继续?",
$"将对 {Settings.FullAudioResourcePath} 下所有文件重新应用导入设置,确认继续?",
"确认", "取消"))
{
Run();
@@ -43,10 +60,10 @@ namespace OCES.Audio
{
// 1. 加载配置表
var audioObjectConfig =
AudioConfigLoader.Load<AudioObjectConfig>(AudioExtendSettings.Instance.FullAudioConfigPath,
AudioConfigLoader.Load<AudioObjectConfig>(Settings.FullAudioConfigPath,
"AudioObject.bytes");
var musicSegmentConfig =
AudioConfigLoader.Load<MusicSegmentConfig>(AudioExtendSettings.Instance.FullAudioConfigPath,
AudioConfigLoader.Load<MusicSegmentConfig>(Settings.FullAudioConfigPath,
"MusicSegment.bytes");
if (audioObjectConfig == null || musicSegmentConfig == null)
{
@@ -56,7 +73,7 @@ namespace OCES.Audio
// 2. 扫描文件
List<string> supportedExtensions = new() { ".wav", ".ogg" };
DirectoryInfo dir = new(AudioExtendSettings.Instance.FullAudioResourcePath);
DirectoryInfo dir = new(Settings.FullAudioResourcePath);
FileInfo[] files = dir.GetFiles().Where(f => supportedExtensions.Contains(f.Extension.ToLower())).ToArray();
int total = files.Length, processed = 0, failed = 0;
@@ -116,20 +133,20 @@ namespace OCES.Audio
importer.ClearSampleSettingOverride("iOS");
AudioImporterSampleSettings settings = importer.defaultSampleSettings;
settings.compressionFormat = AudioExtendSettings.Instance.compressionFormat;
settings.compressionFormat = Settings.compressionFormat;
settings.sampleRateSetting = AudioSampleRateSetting.OverrideSampleRate;
settings.preloadAudioData = audioObject?.Haptic != 0;
switch (category)
{
case AudioCategory.Music:
settings.sampleRateOverride = AudioExtendSettings.Instance.musicSampleRate;
settings.quality = AudioExtendSettings.Instance.musicQuality;
settings.sampleRateOverride = Settings.musicSampleRate;
settings.quality = Settings.musicQuality;
if (duration <= AudioExtendSettings.Instance.decompressThreshold)
if (duration <= Settings.decompressThreshold)
{
settings.loadType = AudioClipLoadType.DecompressOnLoad;
}else if (duration >= AudioExtendSettings.Instance.streamingThreshold)
}else if (duration >= Settings.streamingThreshold)
{
settings.loadType = AudioClipLoadType.Streaming;
}
@@ -141,10 +158,10 @@ namespace OCES.Audio
case AudioCategory.Voice:
case AudioCategory.SFX:
default:
settings.sampleRateOverride = AudioExtendSettings.Instance.sfxSampleRate; // 音效2022.3.62f3没有32kHz这一档,要是有的话这一档其实最合适
settings.quality = AudioExtendSettings.Instance.sfxQuality;
settings.sampleRateOverride = Settings.sfxSampleRate; // 音效2022.3.62f3没有32kHz这一档,要是有的话这一档其实最合适
settings.quality = Settings.sfxQuality;
settings.loadType = duration >= AudioExtendSettings.Instance.streamingThreshold
settings.loadType = duration >= Settings.streamingThreshold
? AudioClipLoadType.Streaming
: AudioClipLoadType.DecompressOnLoad;
break;
@@ -0,0 +1,57 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Build;
namespace OCES.Audio.HandWritten.Editor
{
public static class MixingHelper
{
static readonly List<NamedBuildTarget> s_selectedBuildTargets = new()
{
NamedBuildTarget.Android,
NamedBuildTarget.iOS,
NamedBuildTarget.Standalone,
};
static readonly AudioExtendSettings s_audioExtendSettings = AssetDatabase.LoadAssetAtPath<AudioExtendSettings>(AssetDatabase.GUIDToAssetPath("de80878c933394e2da0966a1466fd793"));
[MenuItem("Tools/OCES/Audio/Enable Mixing")]
public static void EnableMixing()
{
if (s_audioExtendSettings is not null && s_audioExtendSettings.useAssetBundle)
{
EditorUtility.DisplayDialog("Mixing", "已启用Asset Bundle。\n对音频文件的调整不会生效。", "好吧");
}
foreach (NamedBuildTarget buildTarget in s_selectedBuildTargets)
{
PlayerSettings.GetScriptingDefineSymbols(buildTarget, out string[] defineArray);
List<string> defineList = defineArray.ToList();
if (!defineArray.Contains("AUDIO_MIXING"))
{
defineList.Add("AUDIO_MIXING");
PlayerSettings.SetScriptingDefineSymbols(buildTarget, defineList.ToArray());
}
}
}
[MenuItem("Tools/OCES/Audio/Disable Mixing")]
public static void DisableMixing()
{
foreach (NamedBuildTarget buildTarget in s_selectedBuildTargets)
{
PlayerSettings.GetScriptingDefineSymbols(buildTarget, out string[] defineArray);
List<string> defineList = defineArray.ToList();
if (defineList.Contains("AUDIO_MIXING"))
{
defineList.Remove("AUDIO_MIXING");
PlayerSettings.SetScriptingDefineSymbols(buildTarget, defineList.ToArray());
}
}
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 388d2124804048c1a9ea3c403820b443
timeCreated: 1779159928
@@ -29,7 +29,7 @@ namespace OCES.Audio
internal void Restart(MusicContainer container, float inheritedBpm, double dspTime, double startOffset = 0d)
{
Debug.Log($"[BeatClock] Restarting {container.Id}, inheritedBpm = {inheritedBpm}, dspTime = {dspTime}");
//Debug.Log($"[BeatClock] Restarting {container.Id}, inheritedBpm = {inheritedBpm}, dspTime = {dspTime}");
StopAll();
this.m_blendError = this.m_stopped = false;
this.m_containerId = container.Id;
@@ -354,7 +354,7 @@ namespace OCES.Audio
source.loop = false;
source.volume = volumeScale;
source.Play();
Debug.Log($"[LongAudioContainerPlayer] Playing {segment.Name} at {AudioSettings.dspTime}");
//Debug.Log($"[LongAudioContainerPlayer] Playing {segment.Name} at {AudioSettings.dspTime}");
if (isLoop && segment.StartOffset > 0)
{
@@ -104,6 +104,11 @@ namespace OCES.Haptic
{
HapticController.Stop();
}
public void EnableHaptic(bool enable)
{
HapticController.hapticsEnabled = enable;
}
void Awake()
{
+1 -1
View File
@@ -15,7 +15,7 @@ MonoBehaviour:
audioConfigPath: AudioData
audioResourcePath: Audios
audioMixerPath: Audios/Master
useAssetBundle: 1
useAssetBundle: 0
audioBundlePath: Bundles/audios.ab
sfxGroupPath: Master/Regular/SFX
voiceGroupPath: Master/Regular/Voice
+2 -2
View File
@@ -9,7 +9,7 @@ AudioManager:
Doppler Factor: 1
Default Speaker Mode: 2
m_SampleRate: 44100
m_DSPBufferSize: 256
m_DSPBufferSize: 512
m_VirtualVoiceCount: 512
m_RealVoiceCount: 32
m_EnableOutputSuspension: 0
@@ -17,4 +17,4 @@ AudioManager:
m_AmbisonicDecoderPlugin:
m_DisableAudio: 0
m_VirtualizeEffects: 1
m_RequestedDSPBufferSize: 256
m_RequestedDSPBufferSize: 512
+6 -6
View File
@@ -20,7 +20,7 @@ PlayerSettings:
m_ShowUnitySplashScreen: 1
m_ShowUnitySplashLogo: 1
m_SplashScreenOverlayOpacity: 1
m_SplashScreenAnimation: 1
m_SplashScreenAnimation: 0
m_SplashScreenLogoStyle: 1
m_SplashScreenDrawMode: 0
m_SplashScreenBackgroundAnimationZoom: 1
@@ -42,8 +42,8 @@ PlayerSettings:
m_SplashScreenLogos: []
m_VirtualRealitySplashScreen: {fileID: 0}
m_HolographicTrackingLossScreen: {fileID: 0}
defaultScreenWidth: 1920
defaultScreenHeight: 1080
defaultScreenWidth: 540
defaultScreenHeight: 1200
defaultScreenWidthWeb: 960
defaultScreenHeightWeb: 600
m_StereoRenderingPath: 0
@@ -80,7 +80,7 @@ PlayerSettings:
androidPredictiveBackSupport: 1
defaultIsNativeResolution: 1
macRetinaSupport: 1
runInBackground: 0
runInBackground: 1
captureSingleScreen: 0
muteOtherAudioSources: 0
Prepare IOS For Recording: 0
@@ -104,8 +104,8 @@ PlayerSettings:
xboxEnableKinectAutoTracking: 0
xboxEnableFitness: 0
visibleInBackground: 1
allowFullscreenSwitch: 1
fullscreenMode: 1
allowFullscreenSwitch: 0
fullscreenMode: 3
xboxSpeechDB: 0
xboxEnableHeadOrientation: 0
xboxEnableGuest: 0
+12
View File
@@ -72,6 +72,18 @@ AudioSystem.Instance.SetState(MyCustomEnum.SomeState); // 需先通过 StateGro
- 游戏启动时的首次状态设置**必须放在 `Start` 内**,晚一点可以,早了容易出问题。
- 若需在其他位置进行首次初始化,请注释掉 `AudioSystem.Start()` 中的相关代码。
### 开关
```csharp
AudioSystem.Instance.SetMusicVolume(float tatgetVolume) //设置音乐音量 -800
AudioSystem.Instance.SetSFXVolume(float tatgetVolume) //设置音效音量 -800
AudioSystem.Instance.SetMusicState(bool enable) // 启用/禁用音乐
AudioSystem.Instance.SetSFXState(bool enable) // 启用/禁用音效
HapticSytem.Instance.EnableHaptic(bool enable) // 启用/禁用触感系统
```
### Inspector 参数
| 字段 | 说明 |