Files
back_cantanBuilding/Assets/Scripts/Core/SoundMgr.cs
2026-05-26 16:15:54 +08:00

611 lines
23 KiB
C#

using UnityEngine;
using asap.core;
using UnityEngine.AddressableAssets;
using System.Collections.Generic;
using UniRx;
using GameCore;
using cfg;
using Task = System.Threading.Tasks.Task;
using game;
using UnityEngine.ResourceManagement.AsyncOperations;
using System.Linq;
namespace Game
{
public struct ChangeRodDataEvent
{
public ChangeRodDataEvent(int rodId)
{
RodId = rodId;
}
public int RodId;
}
public interface IEventData
{
public SoundType audioType { set; get; }
public string audioNameStr { set; get; }
public float time { set; get; }
}
public class EventFishingSound : IEventData
{
public EventFishingSound(SoundType audioName, float time = 0, bool loop = false)
{
this.audioType = audioName;
this.audioNameStr = audioName.ToString();
this.time = time;
this.loop = loop;
}
public EventFishingSound(string audioName, float time = 0)
{
this.audioType = SoundType.Fishing;
this.audioNameStr = audioName;
this.time = time;
}
public Sound Sound { set; get; }
public SoundType audioType { set; get; }
public string audioNameStr { set; get; }
public float time { set; get; }
public bool loop { set; get; }
}
public class EventUISound : IEventData
{
public EventUISound(SoundType audioName, float time = 0)
{
this.audioType = audioName;
this.audioNameStr = audioName.ToString();
this.time = time;
}
public EventUISound(string audioName, float time = 0)
{
this.audioType = SoundType.UI;
this.audioNameStr = audioName;
this.time = time;
}
public Sound Sound { set; get; }
public SoundType audioType { set; get; }
public string audioNameStr { set; get; }
public float time { set; get; }
}
public class EventBGMSound : IEventData
{
public EventBGMSound(string audioName, float time = 0)
{
this.audioType = SoundType.BGM;
this.audioNameStr = audioName;
this.time = time;
}
public SoundType audioType { set; get; }
public string audioNameStr { set; get; }
public float time { set; get; }
}
public class FadeOutEvent
{
public FadeOutEvent(Sound sound, float timer = 0.5f)
{
this.sound = sound;
this.timer = timer;
}
public Sound sound { set; get; }
public float timer { set; get; }
}
public struct SoundMuteEvent
{
public SoundMuteEvent(int muteType)
{
this.muteType = muteType;
}
public int muteType;
}
public class AssetReferenceAudioClip
{
public AssetReferenceAudioClip(AssetReferenceT<AudioClip> assetReference, bool isOutDisable = false, SoundMainType mainType = SoundMainType.UI, float time = 0)
{
this.assetReference = assetReference;
this.time = time;
this.mainType = mainType;
this.isOutDisable = isOutDisable;
}
public AssetReferenceT<AudioClip> assetReference;
public Sound Sound { set; get; }
public float time { set; get; }
public SoundMainType mainType { set; get; }
public bool isOutDisable = false;
}
public class AssetReferenceAudioVoiceClip
{
public AssetReferenceAudioVoiceClip(AssetReferenceT<AudioClip> assetReference)
{
this.assetReference = assetReference;
}
public AssetReferenceT<AudioClip> assetReference;
public Sound Sound { set; get; }
}
public class OnSoundStateEvent
{
public OnSoundStateEvent(int type)
{
this.type = type;
}
public int type;
}
public class SoundMgr
{
[Inject]
public ISoundService soundService { set; get; }
public Tables _tables { set; get; }
string[] residentFish =
{ SoundType.audio_fishing_waiting.ToString(),
SoundType.audio_fishing_waiting_fishgathering.ToString(),
"audio_fishing_drawing_hpevent_01", "audio_fishing_drawing_hpevent_02","audio_fishing_drawing_hpevent_03","audio_fishing_drawing_hpevent_04","audio_fishing_drawing_hpevent_05",
SoundType.audio_fishing_welldone.ToString(),
SoundType.audio_fishing_switchrod.ToString(),
SoundType.audio_ui_targetcollect_collecting.ToString(),
SoundType.audio_ui_targetcollect_fly.ToString(),
"audio_fishing_pulling_fishflapping_01","audio_fishing_pulling_fishflapping_02","audio_fishing_pulling_fishflapping_03",
SoundType.audio_ui_fishingmap_btn_levelup.ToString(),
SoundType.audio_ui_fishingmap_fishpointfly.ToString(),
SoundType.audio_fishing_dash.ToString(),
SoundType.audio_fishing_fail_forcetoobig.ToString(),
SoundType.audio_fishing_fail_forcetoosmall.ToString(),
"audio_fishing_piercing01","audio_fishing_piercing02","audio_fishing_piercing03",
};
Dictionary<string, AudioClip> residentClip;
Sound BGM_Sound;
AudioClip BGM_Clip;
RodSkinData rodData;
OnSoundStateEvent onSoundState = new OnSoundStateEvent(0);
string BGMName;
protected CompositeDisposable disposables;
public async Task Init(System.Action<float> progress)
{
//playerData = GContext.container.Resolve<PlayerData>();
_tables = GContext.container.Resolve<cfg.Tables>();
//var service = (SoundService)soundService;
await soundService.InitAsync();
var opMap = new Dictionary<string, AsyncOperationHandle<AudioClip>>();
foreach (var addr in residentFish)
{
opMap[addr] = Addressables.LoadAssetAsync<AudioClip>(addr);
}
var tasks = opMap.Values.Select(_ => _.Task);
var total = (float)tasks.Count();
while (true)
{
var completed = tasks.Count(_ => _.IsCompleted);
if (completed == total)
{
progress.Invoke(1f);
break;
}
else
{
progress.Invoke(completed / total);
}
await Awaiters.NextFrame;
}
residentClip = opMap.ToDictionary(_ => _.Key, _ => _.Value.Result);
disposables = new CompositeDisposable();
GContext.OnEvent<EventUISound>().Subscribe(PlaySound).AddTo(disposables);
GContext.OnEvent<EventFishingSound>().Subscribe(PlayFishingSound).AddTo(disposables);
GContext.OnEvent<EventBGMSound>().Subscribe(PlayMusic).AddTo(disposables);
GContext.OnEvent<FadeOutEvent>().Subscribe(FadeOutEvent).AddTo(disposables);
GContext.OnEvent<AssetReferenceAudioClip>().Subscribe(PlaySoundByReference).AddTo(disposables);
GContext.OnEvent<AssetReferenceAudioVoiceClip>().Subscribe(PlayVoiceSoundByReference).AddTo(disposables);
GContext.OnEvent<ChangeRodDataEvent>().Subscribe(OnChangeRodData).AddTo(disposables);
GContext.OnEvent<SoundMuteEvent>().Subscribe(OnSoundMute).AddTo(disposables);
GContext.OnEvent<OnSoundStateEvent>().Subscribe(OnSoundStateEvent).AddTo(disposables);
soundService.BGMVol = GContext.container.Resolve<ISettingService>().Music ? 80 : 0;
soundService.SFXVol = GContext.container.Resolve<ISettingService>().Sound ? 80 : 0;
soundService.VoiceVol = GContext.container.Resolve<ISettingService>().Sound ? 80 : 0;
}
void OnSoundStateEvent(OnSoundStateEvent onSoundStateEvent)
{
onSoundState = onSoundStateEvent;
SetSoundVolume(onSoundStateEvent.type);
}
void OnSoundMute(SoundMuteEvent soundMuteEvent)
{
if (soundMuteEvent.muteType == 0)
{
soundService.BGMVol = GContext.container.Resolve<ISettingService>().Music ? 80 : 0;
}
else
{
soundService.VoiceVol = GContext.container.Resolve<ISettingService>().Sound ? 80 : 0;
soundService.SFXVol = GContext.container.Resolve<ISettingService>().Sound ? 80 : 0;
}
}
public async void OnChangeRodData(ChangeRodDataEvent changeRodDataEvent)
{
AudioClip audioClip;
if (rodData != null)
{
if (residentClip.TryGetValue(rodData.ThrowingAudio, out audioClip))
{
Addressables.Release(audioClip);
residentClip.Remove(rodData.ThrowingAudio);
}
if (residentClip.TryGetValue(rodData.ReelingAudio, out audioClip))
{
Addressables.Release(audioClip);
residentClip.Remove(rodData.ReelingAudio);
}
if (residentClip.TryGetValue(rodData.LineAudio, out audioClip))
{
Addressables.Release(audioClip);
residentClip.Remove(rodData.LineAudio);
}
if (residentClip.TryGetValue(rodData.ComboOutAudio, out audioClip))
{
Addressables.Release(audioClip);
residentClip.Remove(rodData.ComboOutAudio);
}
if (residentClip.TryGetValue(rodData.ComboLoopAudio, out audioClip))
{
Addressables.Release(audioClip);
residentClip.Remove(rodData.ComboLoopAudio);
}
if (residentClip.TryGetValue(rodData.ComboIntoAudio, out audioClip))
{
Addressables.Release(audioClip);
residentClip.Remove(rodData.ComboIntoAudio);
}
}
int skindID = GContext.container.Resolve<PlayerFishData>().GetRodSkin(changeRodDataEvent.RodId);
rodData = _tables.TbRodSkinData.GetOrDefault(skindID);
audioClip = await Addressables.LoadAssetAsync<AudioClip>(rodData.ThrowingAudio).Task;
residentClip.Add(rodData.ThrowingAudio, audioClip);
audioClip = await Addressables.LoadAssetAsync<AudioClip>(rodData.ReelingAudio).Task;
residentClip.Add(rodData.ReelingAudio, audioClip);
audioClip = await Addressables.LoadAssetAsync<AudioClip>(rodData.LineAudio).Task;
residentClip.Add(rodData.LineAudio, audioClip);
audioClip = await Addressables.LoadAssetAsync<AudioClip>(rodData.ComboOutAudio).Task;
residentClip.Add(rodData.ComboOutAudio, audioClip);
audioClip = await Addressables.LoadAssetAsync<AudioClip>(rodData.ComboLoopAudio).Task;
residentClip.Add(rodData.ComboLoopAudio, audioClip);
audioClip = await Addressables.LoadAssetAsync<AudioClip>(rodData.ComboIntoAudio).Task;
residentClip.Add(rodData.ComboIntoAudio, audioClip);
}
public async void PlaySoundByReference(AssetReferenceAudioClip eventSound)
{
string audioName = eventSound.assetReference.AssetGUID;
if (!residentClip.TryGetValue(audioName, out var audioClip) || audioClip == null)
{
if (audioClip == null)
{
residentClip.Remove(audioName);
}
var audioClipL = await Addressables.LoadAssetAsync<AudioClip>(eventSound.assetReference).Task;//.LoadAssetAsync<AudioClip>().Task;
if (disposables == null)
{
return;
}
if (residentClip.TryGetValue(audioName, out audioClip))
{
Addressables.Release(audioClipL);
}
else
{
residentClip.Add(audioName, audioClipL);
audioClip = audioClipL;
}
}
if (audioClip == null)
{
soundService.ReturnSound(eventSound.Sound);
eventSound.Sound = null;
return;
}
SoundMainType soundMainType = eventSound.mainType;
Sound sound;
switch (soundMainType)
{
case SoundMainType.BGM:
await PlayBGM(audioClip, eventSound.time);
residentClip.Remove(audioName);
if (disposables == null)
{
return;
}
return;
case SoundMainType.Fishing:
sound = soundService.GetNewFishingSound(audioClip, time: eventSound.time);
sound.soundMainType = SoundMainType.Fishing;
break;
case SoundMainType.Voice:
SetSoundVolume(2);
sound = soundService.GetNewVoiceSound(audioClip);
sound.soundMainType = SoundMainType.Voice;
break;
case SoundMainType.UILoop:
sound = soundService.GetNewUISound(audioClip, loop: true, time: eventSound.time);
sound.soundMainType = SoundMainType.UI;
break;
case SoundMainType.UI:
default:
sound = soundService.GetNewUISound(audioClip, time: eventSound.time);
sound.soundMainType = SoundMainType.UI;
break;
}
if (sound != null)
{
sound.audioSource.Play();
eventSound.Sound = sound;
await Awaiters.Seconds(audioClip.length);
if (eventSound.Sound.soundMainType == SoundMainType.Voice)
{
SetSoundVolume(onSoundState.type);
}
if (soundMainType == eventSound.Sound.soundMainType && !eventSound.isOutDisable)
{
soundService.ReturnSound(sound);
eventSound.Sound = null;
}
}
}
async void PlayVoiceSoundByReference(AssetReferenceAudioVoiceClip eventSound)
{
var audioClip = await Addressables.LoadAssetAsync<AudioClip>(eventSound.assetReference).Task; // eventSound.assetReference.LoadAssetAsync<AudioClip>().Task;
if (audioClip == null)
{
eventSound.Sound = null;
return;
}
SetSoundVolume(2);
var sound = soundService.GetNewVoiceSound(audioClip);
sound.soundMainType = SoundMainType.Voice;
sound.audioSource.Play();
eventSound.Sound = sound;
await Awaiters.Seconds(audioClip.length);
if (eventSound.Sound.soundMainType == SoundMainType.Voice)
{
SetSoundVolume(onSoundState.type);
soundService.ReturnSound(sound);
}
Addressables.Release(audioClip);
eventSound.Sound = null;
}
/// <summary>
/// 0默认 type==1 钓鱼 type==2 人声
/// </summary>
/// <param name="type"></param>
void SetSoundVolume(int type)
{
if (GContext.container.Resolve<ISettingService>().Music)
{
soundService.BGMVol = type == 0 ? 80 : 72;
}
if (GContext.container.Resolve<ISettingService>().Sound)
{
soundService.SFXVol = type == 2 ? 70 : 80;
}
}
public async void PlaySound(EventUISound eventSound)
{
string audioName = GetAudioName(eventSound);
if (!residentClip.TryGetValue(audioName, out var audioClip))
{
var audioClipL = await Addressables.LoadAssetAsync<AudioClip>(audioName).Task;
if (residentClip.TryGetValue(audioName, out audioClip))
{
Addressables.Release(audioClipL);
}
else
{
residentClip.Add(audioName, audioClipL);
audioClip = audioClipL;
}
}
if (audioClip == null)
{
eventSound.Sound = null;
return;
}
var sound = soundService.GetNewUISound(audioClip, time: eventSound.time);
sound.soundMainType = SoundMainType.UI;
sound.audioSource.Play();
eventSound.Sound = sound;
await Awaiters.Seconds(audioClip.length);
if (SoundMainType.UI == eventSound.Sound.soundMainType)
{
soundService.ReturnSound(sound);
}
eventSound.Sound = null;
}
public async void PlayFishingSound(EventFishingSound eventSound)
{
string audioName = GetAudioName(eventSound);
if (!residentClip.TryGetValue(audioName, out var audioClip))
{
var audioClipL = await Addressables.LoadAssetAsync<AudioClip>(audioName).Task;
if (residentClip.TryGetValue(audioName, out audioClip))
{
Addressables.Release(audioClipL);
}
else
{
residentClip.Add(audioName, audioClipL);
audioClip = audioClipL;
}
}
if (audioClip == null)
{
eventSound.Sound = null;
return;
}
bool isLoop = eventSound.loop;
//if (eventSound.audioType == SoundType.LineAudioReeling || eventSound.audioType == SoundType.ReelingAudioReeling)
//{
// isLoop = true;
//}
var sound = soundService.GetNewFishingSound(audioClip, loop: isLoop, time: eventSound.time);
sound.soundMainType = SoundMainType.Fishing;
sound.audioSource.Play();
eventSound.Sound = sound;
if (!isLoop)
{
await Awaiters.Seconds(audioClip.length);
if (eventSound.Sound != null && SoundMainType.Fishing == eventSound.Sound.soundMainType)
{
soundService.ReturnSound(sound);
}
eventSound.Sound = null;
}
}
public async void PlayMusic(EventBGMSound eventSound)
{
string audioName = GetAudioName(eventSound);
if (BGMName == audioName)
{
return;
}
var audioClip = await Addressables.LoadAssetAsync<AudioClip>(audioName).Task;
if (BGMName == audioName)
{
Addressables.Release(audioClip);
return;
}
await PlayBGM(audioClip, eventSound.time);
}
async Task PlayBGM(AudioClip audioClip, float time = 0)
{
if (audioClip == null)
{
return;
}
BGMName = audioClip.name;
if (BGM_Clip != null)
{
AudioClip audioClip1 = BGM_Clip;
BGM_Clip = null;
Sound bgm_Sound = BGM_Sound;
BGM_Sound = null;
soundService.FadeOut(bgm_Sound, 0.5f);
await Task.Delay(500);
Addressables.Release(audioClip1);
soundService.ReturnSound(bgm_Sound);
}
if (BGMName != audioClip.name)
{
return;
}
BGM_Sound = soundService.GetNewBgmSound(audioClip, time: time);
BGM_Sound.soundMainType = SoundMainType.BGM;
BGM_Clip = audioClip;
BGM_Sound.audioSource.Play();
soundService.FadeIn(BGM_Sound, 0.5f);
}
public void SetBGM(AudioClip audioClip)
{
if (audioClip == BGM_Clip)
return;
if (BGM_Sound == null)
{
BGM_Sound = soundService.GetNewBgmSound(audioClip);
}
BGM_Sound.audioSource.clip = audioClip;
BGM_Sound.soundMainType = SoundMainType.BGM;
BGM_Clip = audioClip;
BGM_Sound.audioSource.Play();
}
void FadeOutEvent(FadeOutEvent fadeOutEvent)
{
_ = FadeOutAsync(fadeOutEvent.sound, fadeOutEvent.timer);
fadeOutEvent.sound = null;
}
async Task FadeOutAsync(Sound sound, float timer = 0.5f)
{
if (sound == null)
{
return;
}
if (sound.soundMainType == SoundMainType.Voice)
{
SetSoundVolume(onSoundState.type);
}
if (sound.soundMainType == SoundMainType.BGM)
{
return;
}
soundService.FadeOut(sound, timer);
await Task.Delay((int)(timer * 1000));
if (sound.soundMainType != SoundMainType.None)
{
soundService.ReturnSound(sound);
}
}
string GetAudioName(IEventData eventData)
{
PlayerData playerData = GContext.container.Resolve<PlayerData>();
PlayerFishData playerFishData = GContext.container.Resolve<PlayerFishData>();
int skindID = playerFishData.GetRodSkin(playerData.equipRodID);
RodSkinData rodSkinData = _tables.TbRodSkinData.GetOrDefault(skindID);
switch (eventData.audioType)
{
case SoundType.ThrowingAudio:
return rodSkinData.ThrowingAudio;
case SoundType.ReelingAudio:
case SoundType.ReelingAudioReeling:
return rodSkinData.ReelingAudio;
case SoundType.LineAudioReeling:
return rodSkinData.LineAudio;
case SoundType.ComboOutAudio:
return rodSkinData.ComboOutAudio;
case SoundType.ComboLoopAudio:
return rodSkinData.ComboLoopAudio;
case SoundType.ComboIntoAudio:
return rodSkinData.ComboIntoAudio;
case SoundType.HPEvent:
return "audio_fishing_drawing_hpevent_0" + Random.Range(1, 6);
case SoundType.audio_fishing_piercing:
return "audio_fishing_piercing0" + Random.Range(1, 4);
case SoundType.audio_fishing_jumpout:
return "audio_fishing_jumpout_0" + Random.Range(1, 4);
case SoundType.audio_fishing_jumpinto:
return "audio_fishing_jumpinto_0" + Random.Range(1, 4);
case SoundType.BGM:
case SoundType.Fishing:
case SoundType.UI:
default:
return eventData.audioNameStr;
}
}
public void Release()
{
disposables?.Dispose();
disposables = null;
residentClip.Clear();
soundService.Release();
foreach (var item in residentClip)
{
Addressables.Release(item.Value);
}
Addressables.Release(BGM_Clip);
GameObject.Destroy(BGM_Sound.gameObject);
BGM_Sound = null;
BGM_Clip = null;
BGMName = null;
}
}
}