feat: Add switch container functionality

This commit is contained in:
2026-04-15 21:05:17 +08:00
parent c62cb4f37b
commit ca6fff2717
57 changed files with 719 additions and 75 deletions
Binary file not shown.
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: a4397a33fe4d245cc99d63997647d8cd
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 64e1436220f4d401995ec856766c2e7a
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 6aa709a35a9da42029251eb3819256cf
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: e01161c5ac9a44c29826c87aef56bc85
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 61608f7e047d4485bbc30b5ddd8cec5e
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: cbe1f9ae435844fc68535585de6a7968
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 5c8f89c6913b4476fa87963914fbd8ad
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 0c17690bc257842a596a6506d05faaac
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 115a82924c82b432b9b9d1639dd840ea
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 50382ffb9ae0941d191a1fab99d72ed8
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 6db1f59903e64438a9ec6c5bfb6b356a
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: f30159797c65949c4b62554227e06ab7
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 8c2fd558ca9764b088c75fd1ac9b33fc
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 787f7f6573521464c83b4db264b42338
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: c1da157e1c4ef48488cf20c909aca237
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 500927f6125c8460da8b59798919f8c5
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: bcae844b708874c8d93054abbff8f578
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 0f7651a5f9baa4e1a9ce848455f6a5e5
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: bd51e45fa0b7745f4b2a3368868e7cf4
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 86e2506072cae4ddca84c3a1719a1860
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 8616f153dfd974b99b6f48ac3a87d6fc
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 2
sampleRateOverride: 22050
compressionFormat: 1
quality: 0.5
conversionMode: 0
preloadAudioData: 1
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:
+5 -5
View File
@@ -192,7 +192,7 @@ MonoBehaviour:
m_HorizontalOverflow: 0 m_HorizontalOverflow: 0
m_VerticalOverflow: 0 m_VerticalOverflow: 0
m_LineSpacing: 1 m_LineSpacing: 1
m_Text: SetState(Game) m_Text: SetState(Ice)
--- !u!222 &17265521 --- !u!222 &17265521
CanvasRenderer: CanvasRenderer:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -344,7 +344,7 @@ MonoBehaviour:
m_BestFit: 0 m_BestFit: 0
m_MinSize: 10 m_MinSize: 10
m_MaxSize: 40 m_MaxSize: 40
m_Alignment: 0 m_Alignment: 4
m_AlignByGeometry: 0 m_AlignByGeometry: 0
m_RichText: 0 m_RichText: 0
m_HorizontalOverflow: 1 m_HorizontalOverflow: 1
@@ -702,7 +702,7 @@ MonoBehaviour:
m_HorizontalOverflow: 0 m_HorizontalOverflow: 0
m_VerticalOverflow: 0 m_VerticalOverflow: 0
m_LineSpacing: 1 m_LineSpacing: 1
m_Text: SetState(Guitar) m_Text: SetState(Cloud)
--- !u!222 &519563563 --- !u!222 &519563563
CanvasRenderer: CanvasRenderer:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -1881,7 +1881,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 2ce47fe7df364a8fa37501256e5b5155, type: 3} m_Script: {fileID: 11500000, guid: 2ce47fe7df364a8fa37501256e5b5155, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
targetGameState: 4 targetGameState: 2
enableLowpass: 0 enableLowpass: 0
--- !u!114 &1542973985 --- !u!114 &1542973985
MonoBehaviour: MonoBehaviour:
@@ -2319,7 +2319,7 @@ MonoBehaviour:
m_HorizontalOverflow: 0 m_HorizontalOverflow: 0
m_VerticalOverflow: 0 m_VerticalOverflow: 0
m_LineSpacing: 1 m_LineSpacing: 1
m_Text: SetState(Home) m_Text: SetState(Normal)
--- !u!222 &1798358789 --- !u!222 &1798358789
CanvasRenderer: CanvasRenderer:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -9,9 +9,12 @@ namespace OCES.Audio
{ {
public const uint GameState = 1; public const uint GameState = 1;
public const uint TileMaterial = 2;
public static void RegisterAllGameState() public static void RegisterAllGameState()
{ {
StateGroupRegistry.Register<GameState>(1); StateGroupRegistry.Register<GameState>(1);
StateGroupRegistry.Register<TileMaterial>(2);
} }
} }
} }
@@ -15,4 +15,11 @@ namespace OCES.Audio
Bass = 6, // 测试用值 Bass = 6, // 测试用值
} }
public enum TileMaterial
{
Normal, // 普通牌
Ice, // 冰
Cloud, // 云
}
} }
@@ -98,6 +98,7 @@ public partial class AudioObject : IBinarySerializable
/// 0 = 随机播放 /// 0 = 随机播放
/// 1 = 顺序播放 /// 1 = 顺序播放
/// 2 = 混合播放 /// 2 = 混合播放
/// 3 = 切换播放
/// </summary> /// </summary>
public ContainerType ContainerType { get; set; } public ContainerType ContainerType { get; set; }
@@ -147,6 +148,16 @@ public partial class AudioObject : IBinarySerializable
/// </summary> /// </summary>
public int VolumeStep { get; set; } public int VolumeStep { get; set; }
/// <summary>
/// 要绑定的 StateGroup ID
/// </summary>
public uint SwitchGroupId { get; set; }
/// <summary>
/// 匹配失败时的备用 AudioObject ID
/// </summary>
public uint DefaultSwitchId { get; set; }
public void DeSerialize(BinaryReader reader) public void DeSerialize(BinaryReader reader)
{ {
@@ -186,6 +197,8 @@ public partial class AudioObject : IBinarySerializable
VolumeStepThreshold = reader.ReadUInt32(); VolumeStepThreshold = reader.ReadUInt32();
Volume = reader.ReadInt32(); Volume = reader.ReadInt32();
VolumeStep = reader.ReadInt32(); VolumeStep = reader.ReadInt32();
SwitchGroupId = reader.ReadUInt32();
DefaultSwitchId = reader.ReadUInt32();
} }
public void Serialize(BinaryWriter writer) public void Serialize(BinaryWriter writer)
@@ -225,6 +238,8 @@ public partial class AudioObject : IBinarySerializable
writer.Write(VolumeStepThreshold); writer.Write(VolumeStepThreshold);
writer.Write(Volume); writer.Write(Volume);
writer.Write(VolumeStep); writer.Write(VolumeStep);
writer.Write(SwitchGroupId);
writer.Write(DefaultSwitchId);
} }
} }
@@ -73,53 +73,36 @@ public static class AudioObjectDefinitions
{ "NVHeartbeats", 56 }, { "NVHeartbeats", 56 },
{ "au_sfx_notice_level_countDown_edge", 57 }, { "au_sfx_notice_level_countDown_edge", 57 },
{ "au_sfx_notice_level_countDown_time", 58 }, { "au_sfx_notice_level_countDown_time", 58 },
{ "sfx_amb_desert", 2000 }, { "0,62", 59 },
{ "sfx_amb_forest", 2001 }, { "1,65", 59 },
{ "sfx_anim_common_item_fly", 3000 }, { "2,68", 59 },
{ "sfx_anim_corePlay_character_footstep_grass", 3001 }, { "0,63", 60 },
{ "sfx_anim_corePlay_character_footstep_sand", 3002 }, { "1,66", 60 },
{ "sfx_anim_corePlay_character_footstep_stone", 3003 }, { "2,69", 60 },
{ "sfx_anim_corePlay_fireBall", 3004 }, { "0,64", 61 },
{ "sfx_anim_corePlay_freeze", 3005 }, { "1,67", 61 },
{ "sfx_anim_corePlay_getIn_devil", 3006 }, { "2,70", 61 },
{ "sfx_anim_corePlay_getIn_dragon", 3007 }, { "au_coreplay_choose_v120_a", 62 },
{ "sfx_anim_corePlay_getIn_ghost", 3008 }, { "au_coreplay_unchoose_v120_a", 63 },
{ "sfx_anim_corePlay_newBoxFromStorage", 3009 }, { "au_coreplay_clear_v120_a", 64 },
{ "sfx_anim_corePlay_shield_broke_wood", 3010 }, { "au_sfx_ui_button_corePlay_choose_ice1", 65 },
{ "sfx_anim_corePlay_shield_broke_crystal", 3011 }, { "au_sfx_ui_button_corePlay_choose_ice2", 65 },
{ "sfx_anim_corePlay_shield_broke_eggRoll", 3012 }, { "au_sfx_ui_button_corePlay_choose_ice3", 65 },
{ "sfx_anim_corePlay_shield_show_crystal", 3013 }, { "au_sfx_ui_button_corePlay_unchoose_ice1", 66 },
{ "sfx_anim_corePlay_shield_show_eggRoll", 3014 }, { "au_sfx_ui_button_corePlay_unchoose_ice2", 66 },
{ "sfx_anim_corePlay_shield_show_wood", 3015 }, { "au_sfx_ui_button_corePlay_unchoose_ice3", 66 },
{ "sfx_anim_corePlay_shield_underAttack_wood", 3016 }, { "au_sfx_ui_button_corePlay_clear_ice1", 67 },
{ "sfx_anim_corePlay_shield_underAttack_crystal", 3017 }, { "au_sfx_ui_button_corePlay_clear_ice2", 67 },
{ "sfx_anim_corePlay_shield_underAttack_eggRoll", 3018 }, { "au_sfx_ui_button_corePlay_clear_ice3", 67 },
{ "sfx_anim_corePlay_slow", 3019 }, { "au_sfx_ui_button_corePlay_choose_cloud1", 68 },
{ "sfx_anim_corePlay_speedUp", 3020 }, { "au_sfx_ui_button_corePlay_choose_cloud2", 68 },
{ "sfx_anim_corePlay_useProp_", 3021 }, { "au_sfx_ui_button_corePlay_choose_cloud3", 68 },
{ "sfx_anim_cutScene_in", 3022 }, { "au_sfx_ui_button_corePlay_unchoose_cloud1", 69 },
{ "sfx_anim_cutScene_out", 3023 }, { "au_sfx_ui_button_corePlay_unchoose_cloud2", 69 },
{ "sfx_notice_common_negative", 4000 }, { "au_sfx_ui_button_corePlay_unchoose_cloud3", 69 },
{ "sfx_notice_corePlay_losing", 4001 }, { "au_sfx_ui_button_corePlay_clear_cloud1", 70 },
{ "sfx_notice_corePlay_restart", 4002 }, { "au_sfx_ui_button_corePlay_clear_cloud2", 70 },
{ "sfx_notice_corePlay_warning", 4003 }, { "au_sfx_ui_button_corePlay_clear_cloud3", 70 },
{ "sfx_notice_guide", 4004 },
{ "sfx_notice_spinWheel_click", 4005 },
{ "sfx_notice_spinWheel_getReward", 4006 },
{ "sfx_notice_corePlay_levelStart_hard", 4007 },
{ "sfx_ui_labelSwitch_home", 5000 },
{ "sfx_ui_panel_common_close", 5001 },
{ "sfx_ui_panel_common_open", 5002 },
{ "sfx_ui_panel_continue_open", 5003 },
{ "sfx_ui_panel_corePlay_guide_open", 5004 },
{ "sfx_ui_panel_initPack_open", 5005 },
{ "sfx_ui_panel_piggyBank_close", 5006 },
{ "sfx_ui_panel_piggyBank_open", 5007 },
{ "sfx_ui_panel_removeAds_open", 5008 },
{ "0", 5009 },
{ "sfx_ui_panel_summerPack_open", 5010 },
{ "sfx_ui_panel_unlockItem_open", 5011 },
{ "voice_princess_fear", 9000 },
}; };
public static readonly HashSet<string> AmbiguousNames = new() public static readonly HashSet<string> AmbiguousNames = new()
@@ -147,6 +130,33 @@ public static class AudioObjectDefinitions
"Chinese Number 08", "Chinese Number 08",
"Chinese Number 09", "Chinese Number 09",
"Chinese Number 10", "Chinese Number 10",
"0,62",
"1,65",
"2,68",
"0,63",
"1,66",
"2,69",
"0,64",
"1,67",
"2,70",
"au_sfx_ui_button_corePlay_choose_ice1",
"au_sfx_ui_button_corePlay_choose_ice2",
"au_sfx_ui_button_corePlay_choose_ice3",
"au_sfx_ui_button_corePlay_unchoose_ice1",
"au_sfx_ui_button_corePlay_unchoose_ice2",
"au_sfx_ui_button_corePlay_unchoose_ice3",
"au_sfx_ui_button_corePlay_clear_ice1",
"au_sfx_ui_button_corePlay_clear_ice2",
"au_sfx_ui_button_corePlay_clear_ice3",
"au_sfx_ui_button_corePlay_choose_cloud1",
"au_sfx_ui_button_corePlay_choose_cloud2",
"au_sfx_ui_button_corePlay_choose_cloud3",
"au_sfx_ui_button_corePlay_unchoose_cloud1",
"au_sfx_ui_button_corePlay_unchoose_cloud2",
"au_sfx_ui_button_corePlay_unchoose_cloud3",
"au_sfx_ui_button_corePlay_clear_cloud1",
"au_sfx_ui_button_corePlay_clear_cloud2",
"au_sfx_ui_button_corePlay_clear_cloud3",
}; };
} }
} }
@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace OCES.Audio
{
public partial class AudioObjectConfig
{
Dictionary<uint, Dictionary<int, uint>> m_switchMapping;
internal void PreParseSwitchMappings()
{
this.m_switchMapping = new Dictionary<uint, Dictionary<int, uint>>();
foreach (AudioObject audioObject in AudioObjectList())
{
if (audioObject.ContainerType != ContainerType.Switch) continue;
this.m_switchMapping[audioObject.Id] = ParseSwitchMapping(audioObject);
}
}
public AudioObject GetMappingResult(uint switchContainerId, Enum enumState)
{
if (!this.m_switchMapping.TryGetValue(switchContainerId, out Dictionary<int, uint> switchMapping))
return null;
return switchMapping.TryGetValue(enumState.GetHashCode(), out uint audioObjectId) ? QueryById(audioObjectId) : null;
}
Dictionary<int, uint> ParseSwitchMapping(AudioObject switchContainer)
{
Dictionary<int, uint> switchMapping = new();
foreach (string name in switchContainer.Name)
{
string[] parts = name.Split(',');
if(parts.Length != 2)
{
Debug.LogWarning($"[AudioSystem] 无法解析 Switch Container {switchContainer.Id} 的映射关系!请检查表");
continue;
}
if (!int.TryParse(parts[0].Trim(), out int stateValue))
{
Debug.LogWarning($"[AudioSystem] 无法解析 映射关系!请查表");
continue;
}
if (!uint.TryParse(parts[1].Trim(), out uint childId))
{
Debug.LogWarning("");
continue;
}
switchMapping.Add(stateValue, childId);
}
return switchMapping;
}
internal AudioObject GetDefaultSwitchOrFallback(AudioObject switchContainer)
{
if (switchContainer.DefaultSwitchId == 0)
return null;
AudioObject defaultChildAudioObject = QueryById(switchContainer.DefaultSwitchId);
if (defaultChildAudioObject != null)
return defaultChildAudioObject;
Debug.LogWarning($"[AudioSystem] DefaultSwitch AudioObject {switchContainer.DefaultSwitchId} 不存在。");
return null;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 68c35969f92d4bb0ba3239d852115c53
timeCreated: 1776244015
@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using UnityEngine; using UnityEngine;
using UnityEngine.Audio; using UnityEngine.Audio;
@@ -9,7 +10,9 @@ namespace OCES.Audio
public class AudioSystem : MonoBehaviour public class AudioSystem : MonoBehaviour
{ {
public static AudioSystem Instance { get; private set; } public static AudioSystem Instance { get; private set; }
// ReSharper disable once MemberCanBePrivate.Global
public IReadOnlyDictionary<Type, Enum> ActiveStates { get; private set; }
const string k_audioConfigPath = "AudioData"; const string k_audioConfigPath = "AudioData";
const string k_audioResourcePath = "Audios"; const string k_audioResourcePath = "Audios";
@@ -20,7 +23,7 @@ namespace OCES.Audio
AudioGroupConfig m_groups; AudioGroupConfig m_groups;
AudioMixer m_mixer; AudioMixer m_mixer;
Tween m_lowpassTween; Tween m_lowpassTween;
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
// 公开接口 // 公开接口
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
@@ -36,6 +39,16 @@ namespace OCES.Audio
public void Play(AudioObject audioObject, Action onPlay = null) public void Play(AudioObject audioObject, Action onPlay = null)
{ {
if (audioObject.ContainerType == ContainerType.Switch)
{
audioObject = ResolveSwitchContainer(audioObject);
if (audioObject == null)
{
Debug.Log("[AudioSystem] 无法解析Switch Container,检查配置表!");
return;
}
}
this.m_sfxSystem.TryPlay(audioObject, onPlay); this.m_sfxSystem.TryPlay(audioObject, onPlay);
} }
@@ -43,8 +56,7 @@ namespace OCES.Audio
{ {
Play((uint)audioId); Play((uint)audioId);
} }
[Obsolete("Use Play(uint) instead")] [Obsolete("Use Play(uint) instead")]
public void Play(string audioName) public void Play(string audioName)
{ {
@@ -108,6 +120,7 @@ namespace OCES.Audio
public void SetState<TEnum>(TEnum state) where TEnum : Enum public void SetState<TEnum>(TEnum state) where TEnum : Enum
{ {
this.m_musicSystem.OnStateChanged(state); this.m_musicSystem.OnStateChanged(state);
ActiveStates = this.m_musicSystem.ActiveStates;
} }
// ───────────────────────────────────────────── // ─────────────────────────────────────────────
@@ -133,6 +146,7 @@ namespace OCES.Audio
AudioSourcePool sfxPool = new(sfxPoolRoot.transform); // 不传 mixer group,让 SfxSystem 自己设置 AudioSourcePool sfxPool = new(sfxPoolRoot.transform); // 不传 mixer group,让 SfxSystem 自己设置
this.m_sfxSystem = gameObject.AddComponent<SfxSystem>(); this.m_sfxSystem = gameObject.AddComponent<SfxSystem>();
this.m_audioObjects = AudioConfigLoader.Load<AudioObjectConfig>($"{k_audioConfigPath}/AudioObject"); this.m_audioObjects = AudioConfigLoader.Load<AudioObjectConfig>($"{k_audioConfigPath}/AudioObject");
this.m_audioObjects.PreParseSwitchMappings();
this.m_groups = AudioConfigLoader.Load<AudioGroupConfig>($"{k_audioConfigPath}/AudioGroup"); this.m_groups = AudioConfigLoader.Load<AudioGroupConfig>($"{k_audioConfigPath}/AudioGroup");
this.m_sfxSystem.Initialize(this.m_groups, this.m_mixer, sfxPool); // 传入 pool this.m_sfxSystem.Initialize(this.m_groups, this.m_mixer, sfxPool); // 传入 pool
@@ -172,10 +186,38 @@ namespace OCES.Audio
// ── 注册 StateGroup ── // ── 注册 StateGroup ──
EnumIds.RegisterAllGameState(); EnumIds.RegisterAllGameState();
ActiveStates = new Dictionary<Type, Enum>();
// ── 启动默认音乐与环境音 ── // ── 启动默认音乐与环境音 ──
// 触发一次初始状态,让音乐系统从默认状态开始匹配 // 触发一次初始状态,让音乐系统从默认状态开始匹配
//SetState(GameState.Home); //SetState(GameState.Home);
} }
AudioObject ResolveSwitchContainer(AudioObject switchContainer)
{
// 遍历 ActiveStates 找到 TypeId 匹配的枚举类型
Enum currentStateValue = null;
bool foundGroup = false;
foreach (KeyValuePair<Type, Enum> keyValuePair in ActiveStates)
{
if (StateGroupRegistry.GetTypeId(keyValuePair.Key) != switchContainer.SwitchGroupId) continue;
currentStateValue = keyValuePair.Value;
foundGroup = true;
break;
}
if (!foundGroup)
{
Debug.LogWarning($"[AudioSystem] Switch Container {switchContainer.Id} 找不到 TypeId={switchContainer.SwitchGroupId} 对应的状态组。");
return this.m_audioObjects.GetDefaultSwitchOrFallback(switchContainer);
}
// 解析AudioObject对象
AudioObject childContainer = this.m_audioObjects.GetMappingResult(switchContainer.Id, currentStateValue);
return childContainer ?? this.m_audioObjects.GetDefaultSwitchOrFallback(switchContainer);
}
} }
public static class AudioConfigLoader public static class AudioConfigLoader
@@ -194,9 +236,9 @@ namespace OCES.Audio
try try
{ {
var config = new T(); T config = new T();
using var ms = new MemoryStream(File.ReadAllBytes(path)); using MemoryStream ms = new(File.ReadAllBytes(path));
using var reader = new BinaryReader(ms); using BinaryReader reader = new(ms);
config.DeSerialize(reader); config.DeSerialize(reader);
return config; return config;
} }
@@ -14,7 +14,7 @@ namespace OCES.Audio.Editor
public Dictionary<uint, int> ClipConcurrentCount = new(); public Dictionary<uint, int> ClipConcurrentCount = new();
public List<ActiveSound> ActiveSounds = new(); public List<ActiveSound> ActiveSounds = new();
public Dictionary<Type, int> ActiveStates = new(); public Dictionary<Type, Enum> ActiveStates = new();
readonly StringBuilder m_stringBuilder = new(); readonly StringBuilder m_stringBuilder = new();
Text m_textComponent; Text m_textComponent;
@@ -35,10 +35,9 @@ namespace OCES.Audio.Editor
this.m_stringBuilder.Clear(); this.m_stringBuilder.Clear();
this.m_stringBuilder.AppendLine("Current States:"); this.m_stringBuilder.AppendLine("Current States:");
foreach (KeyValuePair<Type, int> activeState in this.ActiveStates) foreach (KeyValuePair<Type, Enum> activeState in this.ActiveStates)
{ {
string enumName = Enum.GetName(activeState.Key, activeState.Value) ?? activeState.Value.ToString(); this.m_stringBuilder.AppendLine($"{activeState.Key.Name} is {activeState.Value}");
this.m_stringBuilder.AppendLine($"{activeState.Key.Name} is {enumName}");
} }
this.m_stringBuilder.AppendLine(); this.m_stringBuilder.AppendLine();
@@ -29,6 +29,7 @@ namespace OCES.Audio
Random = 0, Random = 0,
Sequence, Sequence,
Blend, Blend,
Switch,
} }
public enum BlendCrossFadeType public enum BlendCrossFadeType
@@ -84,4 +85,10 @@ namespace OCES.Audio
public partial class MusicPath : IPathEntry { } public partial class MusicPath : IPathEntry { }
public partial class AmbiencePath : IPathEntry { } public partial class AmbiencePath : IPathEntry { }
public class SwitchEntry
{
public uint SwitchValue;
public uint AudioObjectId;
}
} }
@@ -9,8 +9,10 @@ namespace OCES.Audio
/// </summary> /// </summary>
public class MusicStateRouter public class MusicStateRouter
{ {
// key: StateGroup enum Typevalue: 当前激活的 enum 整数值
readonly Dictionary<Type, int> m_activeStates = new(); // key: StateGroup enum Typevalue: 当前激活的 enum 值
readonly Dictionary<Type, Enum> m_activeStates = new();
readonly MusicPathConfig m_musicPaths; readonly MusicPathConfig m_musicPaths;
readonly AmbiencePathConfig m_ambiencePaths; readonly AmbiencePathConfig m_ambiencePaths;
@@ -18,6 +20,7 @@ namespace OCES.Audio
// 上一次匹配到的 PathId,用于 Transition 表的 FromPathId 查询 // 上一次匹配到的 PathId,用于 Transition 表的 FromPathId 查询
public uint LastMusicPathId { get; private set; } public uint LastMusicPathId { get; private set; }
public uint LastAmbiencePathId { get; private set; } public uint LastAmbiencePathId { get; private set; }
internal IReadOnlyDictionary<Type, Enum> ActiveStates { get { return this.m_activeStates; }}
public MusicStateRouter(MusicPathConfig musicPaths, AmbiencePathConfig ambiencePaths) public MusicStateRouter(MusicPathConfig musicPaths, AmbiencePathConfig ambiencePaths)
{ {
@@ -31,8 +34,8 @@ namespace OCES.Audio
public void SetState<TEnum>(TEnum state, out uint musicContainerId, out uint ambienceContainerId) public void SetState<TEnum>(TEnum state, out uint musicContainerId, out uint ambienceContainerId)
where TEnum : Enum where TEnum : Enum
{ {
// Dictionary<Type, int> 天然保证同一 StateGroup 只保留最新值,直接覆盖即可 // Dictionary<Type, Enum> 天然保证同一 StateGroup 只保留最新值,直接覆盖即可
this.m_activeStates[typeof(TEnum)] = Convert.ToInt32(state); this.m_activeStates[typeof(TEnum)] = state;
musicContainerId = MatchBestPath(this.m_musicPaths.MusicPathList(), out uint musicPathId); musicContainerId = MatchBestPath(this.m_musicPaths.MusicPathList(), out uint musicPathId);
ambienceContainerId = MatchBestPath(this.m_ambiencePaths.AmbiencePathList(), out uint ambiencePathId); ambienceContainerId = MatchBestPath(this.m_ambiencePaths.AmbiencePathList(), out uint ambiencePathId);
@@ -99,9 +102,9 @@ namespace OCES.Audio
} }
bool conditionMet = false; bool conditionMet = false;
foreach (KeyValuePair<Type, int> kv in this.m_activeStates) foreach (KeyValuePair<Type, Enum> kv in this.m_activeStates)
{ {
if (StateGroupRegistry.GetTypeId(kv.Key) != typeId || kv.Value != stateValue) if (StateGroupRegistry.GetTypeId(kv.Key) != typeId || Convert.ToInt32(kv.Value) != stateValue)
continue; continue;
conditionMet = true; conditionMet = true;
break; break;
@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using UnityEngine; using UnityEngine;
namespace OCES.Audio namespace OCES.Audio
@@ -16,6 +17,11 @@ namespace OCES.Audio
// 记录上一次两个通道各自匹配到的 PathId,用于查 Transition 表 // 记录上一次两个通道各自匹配到的 PathId,用于查 Transition 表
uint m_lastMusicPathId; uint m_lastMusicPathId;
uint m_lastAmbiencePathId; uint m_lastAmbiencePathId;
internal IReadOnlyDictionary<Type, Enum> ActiveStates
{
get { return this.m_stateRouter.ActiveStates; }
}
public void Initialize( public void Initialize(
MusicSegmentConfig segments, MusicSegmentConfig segments,
@@ -488,8 +488,6 @@ namespace OCES.Audio
DecrementClipCount(active.AudioObject.Id); DecrementClipCount(active.AudioObject.Id);
this.m_activeSounds.Remove(active); this.m_activeSounds.Remove(active);
// TryStopHaptic(active.AudioObject.Haptic);
this.m_pool.ReturnToPool(active.Source.gameObject); this.m_pool.ReturnToPool(active.Source.gameObject);
} }
@@ -511,8 +509,6 @@ namespace OCES.Audio
DecrementClipCount(active.AudioObject.Id); DecrementClipCount(active.AudioObject.Id);
this.m_activeSounds.Remove(active); this.m_activeSounds.Remove(active);
this.m_pool.ReturnToPool(active.Source.gameObject); this.m_pool.ReturnToPool(active.Source.gameObject);
// TryStopHaptic(active.AudioObject.Haptic);
} }
static void TryStartHaptic(ActiveSound active) static void TryStartHaptic(ActiveSound active)
@@ -526,7 +522,6 @@ namespace OCES.Audio
{ {
HapticSystem.Instance.Stop(hapticId); HapticSystem.Instance.Stop(hapticId);
} }
} }
/// <summary> /// <summary>
+1 -1
View File
@@ -7,7 +7,7 @@ namespace OCES
{ {
public class ButtonInvoker : MonoBehaviour public class ButtonInvoker : MonoBehaviour
{ {
public GameState targetGameState; public TileMaterial targetGameState;
public bool enableLowpass; public bool enableLowpass;
Button m_button; Button m_button;