NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Framework/Audio/AudioUnityManager.cs

1317 lines
35 KiB
C#
Raw Normal View History

2025-03-10 13:12:05 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
using Framework;
using PhxhSDK;
using UnityEngine;
using UnityEngine.Audio;
2025-04-16 12:24:10 +08:00
using Constants = Framework.Constants;
2025-03-10 13:12:05 +08:00
using Object = UnityEngine.Object;
2025-11-12 20:09:48 +08:00
public class AudioUnityManager: Singlenton<AudioUnityManager>, IStart, IInitable, IUpdatable
2025-03-10 13:12:05 +08:00
{
public GameObject AudioRoot;
/// <summary>
/// 对象池数量限制
/// </summary>
2025-11-12 19:37:08 +08:00
public int MusicPoolLimit = 1;
2025-03-10 13:12:05 +08:00
public int SoundPoolLimit = 100;
public int SpeakPoolLimit = 1;
/// <summary>
/// 播放音频对象池
/// </summary>
2025-11-13 16:59:52 +08:00
private Dictionary<int, AudioPlayer> _soundAudioDic;
private Dictionary<int, AudioPlayer> _soundAudioLoopDic;
private Dictionary<int, AudioPlayer> _musicAudioDic;
private Dictionary<int, AudioPlayer> _musicAudioLoopDic;
private Dictionary<int, AudioPlayer> _allAudioDic;
2025-03-10 13:12:05 +08:00
private Dictionary<string, long> _playSoundTimeStampDic; //时间戳记录
2025-03-10 13:12:05 +08:00
2025-11-12 19:56:26 +08:00
private Dictionary<AudioPlayType, List<int>> _playingLDic;
2025-03-10 13:12:05 +08:00
2025-11-13 16:59:52 +08:00
private Dictionary<int, AudioPlayer> _storyAudioDic;
2025-04-02 15:00:32 +08:00
public AudioListener GlobalListener; //全局监听
private bool _isFollowCamera = false; //是否跟随相机
2025-03-10 13:12:05 +08:00
#region Property
2025-11-13 18:36:05 +08:00
/// <summary>
/// 音效音量 - 委托到 AudioVolumeSettings
/// </summary>
2025-03-10 13:12:05 +08:00
public float GlobalSoundsVolume
{
2025-11-13 18:36:05 +08:00
get => AudioVolumeSettings.Instance.SoundVolume;
set => AudioVolumeSettings.Instance.SoundVolume = value;
2025-03-10 13:12:05 +08:00
}
2025-11-13 18:36:05 +08:00
/// <summary>
/// 语音音量 - 委托到 AudioVolumeSettings
/// </summary>
public float GlobalSpeakVolume
{
get => AudioVolumeSettings.Instance.SpeakVolume;
set => AudioVolumeSettings.Instance.SpeakVolume = value;
2025-03-10 13:12:05 +08:00
}
2025-11-13 18:36:05 +08:00
/// <summary>
/// 音乐音量 - 委托到 AudioVolumeSettings
/// </summary>
public float GlobalMusicVolume
{
get => AudioVolumeSettings.Instance.MusicVolume;
set => AudioVolumeSettings.Instance.MusicVolume = value;
2025-03-10 13:12:05 +08:00
}
2025-11-13 18:36:05 +08:00
/// <summary>
/// 全局总音量 - 委托到 AudioVolumeSettings
/// </summary>
2025-03-10 13:12:05 +08:00
public float GlobalVolume
{
2025-11-13 18:36:05 +08:00
get => AudioVolumeSettings.Instance.GlobalVolume;
set => AudioVolumeSettings.Instance.GlobalVolume = value;
2025-03-10 13:12:05 +08:00
}
public bool GlobalIsOpenSpeak;
#endregion
#region Framework
public void Start()
{
if (!AudioRoot)
{
AudioRoot = new GameObject();
AudioRoot.name = "Audio(Singleton)";
Object.DontDestroyOnLoad(AudioRoot);
GlobalListener = AudioRoot.AddComponent<AudioListener>();
2025-04-02 15:00:32 +08:00
_InitListenerPos();
2025-03-10 13:12:05 +08:00
}
}
public void Init()
{
2025-11-13 16:59:52 +08:00
_soundAudioDic = new Dictionary<int, AudioPlayer>();
_soundAudioLoopDic = new Dictionary<int, AudioPlayer>();
_musicAudioDic = new Dictionary<int, AudioPlayer>();
_musicAudioLoopDic = new Dictionary<int, AudioPlayer>();
2025-03-10 13:12:05 +08:00
2025-11-13 16:59:52 +08:00
_allAudioDic = new Dictionary<int, AudioPlayer>();
2025-03-10 13:12:05 +08:00
_playingLDic = new ();
2025-11-12 19:56:26 +08:00
_playingLDic.Add(AudioPlayType.Music, new List<int>());
_playingLDic.Add(AudioPlayType.Sound, new List<int>());
_playingLDic.Add(AudioPlayType.Speak, new List<int>());
2025-03-10 13:12:05 +08:00
_storyAudioDic = new();
_playSoundTimeStampDic = new();
2025-04-16 12:24:10 +08:00
EventManager.Instance.Register(EventManager.EventName.Audio_ErrorAudioPlay, _OnErrorAudioPlay);
2025-03-10 13:12:05 +08:00
}
public void Release()
{
2025-04-16 12:24:10 +08:00
EventManager.Instance.Unregister(EventManager.EventName.Audio_ErrorAudioPlay, _OnErrorAudioPlay);
2025-03-10 13:12:05 +08:00
}
public void Update(float dt)
{
2025-04-08 16:50:58 +08:00
_SetListenerPos();
2025-03-10 13:12:05 +08:00
foreach (var kv in _musicAudioDic)
{
var audio = kv.Value;
2025-11-14 19:10:22 +08:00
if (audio.State != PlayState.Stopped)
2025-03-10 13:12:05 +08:00
{
audio.Update(dt);
}
}
foreach (var kv in _musicAudioLoopDic)
{
var audio = kv.Value;
2025-11-14 19:10:22 +08:00
if (audio.State != PlayState.Stopped)
2025-03-10 13:12:05 +08:00
{
audio.Update(dt);
}
}
foreach (var kv in _soundAudioDic)
{
var audio = kv.Value;
2025-11-14 19:10:22 +08:00
if (audio.State != PlayState.Stopped)
2025-03-10 13:12:05 +08:00
{
audio.Update(dt);
}
}
foreach (var kv in _soundAudioLoopDic)
{
var audio = kv.Value;
2025-11-14 19:10:22 +08:00
if (audio.State != PlayState.Stopped)
2025-03-10 13:12:05 +08:00
{
audio.Update(dt);
}
}
foreach (var kv in _storyAudioDic)
{
var audio = kv.Value;
2025-11-14 19:10:22 +08:00
if (audio.State != PlayState.Stopped)
2025-03-10 13:12:05 +08:00
{
audio.Update(dt);
}
}
}
#endregion
#region LoadAsset
private string GetFullPath(string key, bool isI18N = false)
2025-03-10 13:12:05 +08:00
{
var cfg = TableManager.Instance.Tables.AudioSourceConfig.GetOrDefault(key);
if (cfg == null)
{
DebugUtil.LogError($"音频Key{key}找不到!");
return "";
}
var path = cfg.Path;
if (isI18N)
{
if (path.Contains(LanguageManager.I18N))
{
var eLanguage = LanguageManager.Instance.GetCurrentLanguage();
var replacePath = LanguageManager.PathDic[eLanguage];
path = path.Replace(LanguageManager.I18N, replacePath);
}
return path;
}
return cfg.Path;
2025-03-10 13:12:05 +08:00
}
2025-07-28 13:02:07 +08:00
private float _GetNormalizeVolume(string key)
{
var cfg = TableManager.Instance.Tables.AudioSourceConfig.GetOrDefault(key);
if (cfg == null)
{
DebugUtil.LogError($"音频Key{key}找不到!");
return 0f;
}
var volume = cfg.VolumeScale;
return volume;
}
2025-03-10 13:12:05 +08:00
#endregion
#region AudioObj
/// <summary>
/// 获取可用的Audio
/// </summary>
/// <param name="audioType"></param>
/// <returns></returns>
2025-11-14 18:21:45 +08:00
private AudioPlayer _GetUsableAudio(PhxhSDK.AudioType audioType, bool isLoop, bool isSpeak = false)
2025-03-10 13:12:05 +08:00
{
try
{
var limit = _CheckIsAudioLimited(audioType, isSpeak);
if (limit)
{
return _GetOldAudio(audioType, isLoop, isSpeak);
}
var freeAudio = _GetFreeAudio(audioType, isLoop);
return freeAudio ?? _CreateNewAudio(audioType, isLoop);
}
catch (Exception e)
{
DebugUtil.LogError($"AudioManger, GetUsableAudio Fail.{e}");
}
return null;
}
2025-11-14 18:21:45 +08:00
private AudioPlayer _GetOldAudio(PhxhSDK.AudioType audioType, bool isLoop, bool isSpeak)
2025-03-10 13:12:05 +08:00
{
var playingList = _playingLDic[GetPlayType(audioType, isSpeak)];
if (playingList.Count > 0)
{
var audio = GetAudioByID(playingList[0]);
return audio;
}
return _CreateNewAudio(audioType, isLoop);
}
2025-11-14 18:21:45 +08:00
private int _GetLimit(PhxhSDK.AudioType audioType, bool isSpeak)
2025-03-10 13:12:05 +08:00
{
if (isSpeak)
{
return SpeakPoolLimit;
}
2025-11-14 18:21:45 +08:00
if (audioType == PhxhSDK.AudioType.Music)
2025-03-10 13:12:05 +08:00
{
return MusicPoolLimit;
}
2025-11-14 18:21:45 +08:00
if (audioType == PhxhSDK.AudioType.Sound)
2025-03-10 13:12:05 +08:00
{
return SoundPoolLimit;
}
return -1;
}
2025-11-14 18:21:45 +08:00
private AudioPlayType GetPlayType(PhxhSDK.AudioType audioType, bool isSpeak)
2025-03-10 13:12:05 +08:00
{
if (isSpeak)
2025-11-12 19:56:26 +08:00
return AudioPlayType.Speak;
2025-11-14 18:21:45 +08:00
if (audioType == PhxhSDK.AudioType.Music)
2025-11-12 19:56:26 +08:00
return AudioPlayType.Music;
return AudioPlayType.Sound;
2025-03-10 13:12:05 +08:00
}
2025-11-14 18:21:45 +08:00
private bool _CheckIsAudioLimited(PhxhSDK.AudioType audioType, bool isSpeak)
2025-03-10 13:12:05 +08:00
{
var limit = _GetLimit(audioType, isSpeak);
var playingList = _playingLDic[GetPlayType(audioType, isSpeak)];
if (playingList.Count >= limit)
{
return true;
}
return false;
}
2025-11-14 18:21:45 +08:00
private Dictionary<int, AudioPlayer> _GetAudioDic(PhxhSDK.AudioType audioType, bool isLoop)
2025-03-10 13:12:05 +08:00
{
switch (audioType)
{
2025-11-14 18:21:45 +08:00
case PhxhSDK.AudioType.Music:
2025-03-10 13:12:05 +08:00
return isLoop? _musicAudioLoopDic : _musicAudioDic;
2025-11-14 18:21:45 +08:00
case PhxhSDK.AudioType.Sound:
2025-03-10 13:12:05 +08:00
return isLoop? _soundAudioLoopDic : _soundAudioDic;
default:
{
DebugUtil.LogError("获取AudioDic出错传入AudioType有误");
return null;
}
}
}
2025-11-14 18:21:45 +08:00
private AudioPlayer _GetFreeAudio(PhxhSDK.AudioType audioType, bool isLoop)
2025-03-10 13:12:05 +08:00
{
var dic = _GetAudioDic(audioType, isLoop);
if (dic != null)
{
foreach (var kv in dic)
{
var audio = kv.Value;
2025-11-14 19:10:22 +08:00
if (audio.State == PlayState.Stopped)
2025-03-10 13:12:05 +08:00
{
return audio;
}
}
}
return null;
}
2025-11-14 18:21:45 +08:00
private AudioPlayer _CreateStoryAudio(GameObject posGo = null, PhxhSDK.AudioType audioType = PhxhSDK.AudioType.Sound)
2025-03-10 13:12:05 +08:00
{
var rootGo = new GameObject()
{
name = "AudioStory"
};
rootGo.transform.SetParent(AudioRoot.transform);
2025-11-13 16:59:52 +08:00
var audio = new AudioPlayer(audioType, rootGo, null, new AudioInfo(), false, false);
2025-11-17 14:50:15 +08:00
rootGo.name += audio.AudioId;
_storyAudioDic.TryAdd(audio.AudioId, audio);
_allAudioDic.Add(audio.AudioId, audio);
2025-03-10 13:12:05 +08:00
return audio;
}
2025-11-14 18:21:45 +08:00
private AudioPlayer _CreateNewAudio(PhxhSDK.AudioType audioType, bool isLoop)
2025-03-10 13:12:05 +08:00
{
var rootGo = new GameObject()
{
name = "Audio"
};
rootGo.transform.SetParent(AudioRoot.transform);
2025-11-13 16:59:52 +08:00
var audio = new AudioPlayer(audioType, rootGo, null, new AudioInfo(), false, false);
2025-03-10 13:12:05 +08:00
2025-11-14 18:21:45 +08:00
if (audioType == PhxhSDK.AudioType.Music)
2025-03-10 13:12:05 +08:00
{
rootGo.name = "music";
2025-11-17 14:50:15 +08:00
rootGo.name += audio.AudioId;
2025-03-10 13:12:05 +08:00
if (isLoop)
{
rootGo.name += "Loop";
2025-11-17 14:50:15 +08:00
_musicAudioLoopDic.TryAdd(audio.AudioId, audio);
2025-03-10 13:12:05 +08:00
}
else
{
2025-11-17 14:50:15 +08:00
_musicAudioDic.TryAdd(audio.AudioId, audio);
2025-03-10 13:12:05 +08:00
}
}
2025-11-14 18:21:45 +08:00
if (audioType == PhxhSDK.AudioType.Sound)
2025-03-10 13:12:05 +08:00
{
rootGo.name = "Sound";
2025-11-17 14:50:15 +08:00
rootGo.name += audio.AudioId;
2025-03-10 13:12:05 +08:00
if (isLoop)
{
rootGo.name += "Loop";
2025-11-17 14:50:15 +08:00
_soundAudioLoopDic.TryAdd(audio.AudioId, audio);
2025-03-10 13:12:05 +08:00
}
else
{
2025-11-17 14:50:15 +08:00
_soundAudioDic.TryAdd(audio.AudioId, audio);
2025-03-10 13:12:05 +08:00
}
}
2025-11-17 14:50:15 +08:00
_allAudioDic.Add(audio.AudioId, audio);
2025-03-10 13:12:05 +08:00
return audio;
}
#endregion
#region Play
/// <summary>
/// 调用接口传obj
/// </summary>
/// <param name="key"></param>
/// <param name="type"></param>
/// <param name="posObj"></param>
/// <returns></returns>
2025-11-12 19:37:08 +08:00
private int _PlayAudio(string key, AudioPlayType type, GameObject posObj = null, bool isLoop = false,
int priority = AudioConstant.DefaultPriority, bool isFade = false, float fadeTime = 0f)
2025-03-10 13:12:05 +08:00
{
2025-11-13 18:36:05 +08:00
var settings = AudioVolumeSettings.Instance;
2025-03-10 13:12:05 +08:00
switch (type)
{
2025-11-12 19:37:08 +08:00
case AudioPlayType.Sound:
2025-11-13 18:36:05 +08:00
if (settings.GlobalVolume <= 0 || settings.SoundVolume <= 0)
2025-03-10 13:12:05 +08:00
{
return -1;
}
break;
2025-11-12 19:37:08 +08:00
case AudioPlayType.Speak:
2025-11-13 18:36:05 +08:00
if (settings.GlobalVolume <= 0 || settings.SpeakVolume <= 0)
2025-03-10 13:12:05 +08:00
{
return -1;
}
break;
default:
break;
}
if (string.IsNullOrEmpty(key))
{
return -1;
}
switch (type)
{
2025-11-12 19:37:08 +08:00
case AudioPlayType.Music:
2025-03-10 13:12:05 +08:00
{
return _PlayMusic(key, posObj, isLoop, isFade, fadeTime);
}
2025-11-12 19:37:08 +08:00
case AudioPlayType.Sound:
2025-03-10 13:12:05 +08:00
{
return _PlaySound(key, posObj, isLoop, priority, isFade, fadeTime);
2025-03-10 13:12:05 +08:00
}
2025-11-12 19:37:08 +08:00
case AudioPlayType.Speak:
2025-03-10 13:12:05 +08:00
{
return _PlaySpeakSound(key, posObj, isFade, fadeTime);
}
default: break;
}
return -1;
}
/// <summary>
/// 调用接口,传位置
/// </summary>
/// <param name="key"></param>
/// <param name="type"></param>
/// <param name="pos"></param>
/// <returns></returns>
2025-11-12 19:37:08 +08:00
private int _PlayAudio(string key, AudioPlayType type, Vector3 pos, bool loop = false,
int priority = AudioConstant.DefaultPriority, bool isFade = false, float fadeTime = 0f)
2025-03-10 13:12:05 +08:00
{
2025-11-13 18:36:05 +08:00
var settings = AudioVolumeSettings.Instance;
2025-03-10 13:12:05 +08:00
switch (type)
{
2025-11-12 19:37:08 +08:00
case AudioPlayType.Sound:
2025-11-13 18:36:05 +08:00
if (settings.GlobalVolume <= 0 || settings.SoundVolume <= 0)
2025-03-10 13:12:05 +08:00
{
return -1;
}
break;
2025-11-12 19:37:08 +08:00
case AudioPlayType.Speak:
2025-11-13 18:36:05 +08:00
if (settings.GlobalVolume <= 0 || settings.SpeakVolume <= 0)
2025-03-10 13:12:05 +08:00
{
return -1;
}
break;
default:
break;
}
switch (type)
{
2025-11-12 19:37:08 +08:00
case AudioPlayType.Music:
2025-03-10 13:12:05 +08:00
{
return _PlayMusic(key, pos, loop, isFade, fadeTime);
}
2025-11-12 19:37:08 +08:00
case AudioPlayType.Sound:
2025-03-10 13:12:05 +08:00
{
return _PlaySound(key, pos, loop, priority, isFade, fadeTime);
2025-03-10 13:12:05 +08:00
}
2025-11-12 19:37:08 +08:00
case AudioPlayType.Speak:
2025-03-10 13:12:05 +08:00
{
return _PlaySpeakSound(key, pos, isFade, fadeTime);
}
default: break;
}
return -1;
}
private int _PlayMusic(string key, GameObject posObj = null, bool isLoop = true, bool isFade = false, float fadeTime = 0f, float volume = 1f)
{
var path = GetFullPath(key);
if (!isFade)
{
2025-11-14 18:21:45 +08:00
var audio = _GetUsableAudio(PhxhSDK.AudioType.Music, isLoop);
2025-03-10 13:12:05 +08:00
//错误打印,保护
if (audio == null)
{
DebugUtil.LogError($"AudioManager, PlayMusic, Cant GetUsableAudio key:{key}");
return -1;
}
2025-07-28 13:02:07 +08:00
var norVol = _GetNormalizeVolume(key);
audio.SetNormalizeVolume(norVol);
2025-11-13 20:14:42 +08:00
audio.SetFollowTarget(posObj);
2025-03-10 13:12:05 +08:00
audio.SetIsSpeak(false);
2025-11-14 18:21:45 +08:00
audio.SetVolume(volume * norVol);
2025-11-14 19:10:22 +08:00
audio.SetLoop(isLoop);
2025-03-10 13:12:05 +08:00
audio.Play(path);
2025-11-14 19:10:22 +08:00
audio.SetLoop(isLoop);
2025-11-17 14:50:15 +08:00
return audio.AudioId;
2025-03-10 13:12:05 +08:00
}
else
{
2025-11-14 18:21:45 +08:00
var audio = _GetUsableAudio(PhxhSDK.AudioType.Music, isLoop);
2025-11-13 20:14:42 +08:00
audio.SetFollowTarget(posObj);
2025-03-10 13:12:05 +08:00
audio.SetIsSpeak(false);
audio.Stop();
2025-11-14 18:21:45 +08:00
audio.SetVolume(0);
2025-03-10 13:12:05 +08:00
audio.PlayWithFade(path, fadeTime);
2025-11-14 19:10:22 +08:00
audio.SetLoop(isLoop);
2025-11-17 14:50:15 +08:00
return audio.AudioId;
2025-03-10 13:12:05 +08:00
}
}
private int _PlayMusic(string key, Vector3 pos, bool isLoop, bool isFade = false, float fadeTime = 0f, float volume = 1f)
{
2025-11-14 18:21:45 +08:00
var audio = _GetUsableAudio(PhxhSDK.AudioType.Music, isLoop);
2025-03-10 13:12:05 +08:00
var path = GetFullPath(key);
//错误打印,保护
if (audio == null)
{
DebugUtil.LogError($"AudioManager, PlayMusic By Pos, Cant GetUsableAudio key:{key}");
return -1;
}
2025-11-13 20:14:42 +08:00
audio.SetPosition(pos);
2025-03-10 13:12:05 +08:00
audio.SetIsSpeak(false);
2025-07-28 13:02:07 +08:00
var norVol = _GetNormalizeVolume(key);
audio.SetNormalizeVolume(norVol);
2025-03-10 13:12:05 +08:00
2025-11-14 19:10:22 +08:00
audio.SetLoop(true);
2025-03-10 13:12:05 +08:00
audio.Stop();
if (isFade)
{
2025-11-14 18:21:45 +08:00
audio.SetVolume(0);
audio.SetVolume(volume);
2025-03-10 13:12:05 +08:00
audio.PlayWithFade(path, fadeTime);
}
else
{
audio.Play(path);
}
2025-11-14 19:10:22 +08:00
audio.SetLoop(isLoop);
2025-11-17 14:50:15 +08:00
return audio.AudioId;
2025-03-10 13:12:05 +08:00
}
private int _PlaySound(string key, GameObject posObj = null, bool isLoop = false,
int priority = AudioConstant.DefaultPriority, bool isFade = false, float fadeTime = 0f, float volume = 1f)
2025-03-10 13:12:05 +08:00
{
if (GlobalSoundsVolume < 0.01f)
{
return -1;
}
//判断优先级然后设置间隔
if (priority >= AudioConstant.LowPriority)
{
var curTimeStamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
if (_playSoundTimeStampDic.TryGetValue(key, out var timeStamp))
{
if (curTimeStamp - timeStamp < 100)
{
return -1;
}
_playSoundTimeStampDic[key] = curTimeStamp;
}
else
{
_playSoundTimeStampDic.TryAdd(key, curTimeStamp);
}
}
2025-11-14 18:21:45 +08:00
var audio = _GetUsableAudio(PhxhSDK.AudioType.Sound, isLoop);
2025-03-10 13:12:05 +08:00
//错误打印,保护
if (audio == null)
{
DebugUtil.LogError($"AudioManager, PlaySound By Obj, Cant GetUsableAudio key:{key}");
return -1;
}
var path = GetFullPath(key);
audio.Stop();
2025-07-28 13:02:07 +08:00
var norVol = _GetNormalizeVolume(key);
audio.SetNormalizeVolume(norVol);
2025-11-13 20:14:42 +08:00
audio.SetFollowTarget(posObj);
2025-03-10 13:12:05 +08:00
audio.SetIsSpeak(false);
2025-11-14 19:10:22 +08:00
audio.SetLoop(isLoop);
2025-03-10 13:12:05 +08:00
if (posObj)
{
audio.SetIs3D(true);
}
if (isFade)
{
2025-11-14 18:21:45 +08:00
audio.SetVolume(0);
2025-03-10 13:12:05 +08:00
audio.PlayWithFade(path);
}
else
{
2025-11-14 18:21:45 +08:00
audio.SetVolume(volume * norVol);
2025-03-10 13:12:05 +08:00
audio.Play(path);
}
2025-11-14 19:10:22 +08:00
audio.SetLoop(isLoop);
2025-11-17 14:50:15 +08:00
return audio.AudioId;
2025-03-10 13:12:05 +08:00
}
private int _PlaySound(string key, Vector3 pos, bool isLoop = false, int priority = AudioConstant.DefaultPriority,
bool isFade = false, float fadeTime = 0f, float volume = 1f)
2025-03-10 13:12:05 +08:00
{
if (GlobalSoundsVolume < 0.01f)
{
return -1;
}
//判断优先级然后设置间隔
if (priority >= AudioConstant.LowPriority)
{
var curTimeStamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
if (_playSoundTimeStampDic.TryGetValue(key, out var timeStamp))
{
if (curTimeStamp - timeStamp < 100)
{
return -1;
}
_playSoundTimeStampDic[key] = curTimeStamp;
}
else
{
_playSoundTimeStampDic.TryAdd(key, curTimeStamp);
}
}
2025-11-14 18:21:45 +08:00
var audio = _GetUsableAudio(PhxhSDK.AudioType.Sound, isLoop);
2025-03-10 13:12:05 +08:00
//错误打印,保护
if (audio == null)
{
DebugUtil.LogError($"AudioManager, PlaySound By Pos, Cant GetUsableAudio key:{key}");
return -1;
}
var path = GetFullPath(key);
audio.Stop();
2025-07-28 13:02:07 +08:00
var norVol = _GetNormalizeVolume(key);
audio.SetNormalizeVolume(norVol);
2025-11-13 20:14:42 +08:00
audio.SetPosition(pos);
2025-11-14 19:10:22 +08:00
audio.SetLoop(isLoop);
2025-03-10 13:12:05 +08:00
audio.SetIsSpeak(false);
audio.SetIs3D(true);
if (isFade)
{
2025-11-14 18:21:45 +08:00
audio.SetVolume(0);
2025-03-10 13:12:05 +08:00
audio.PlayWithFade(path, fadeTime);
}
else
{
2025-11-14 18:21:45 +08:00
audio.SetVolume(volume * norVol);
2025-03-10 13:12:05 +08:00
audio.Play(path);
}
2025-11-14 19:10:22 +08:00
audio.SetLoop(isLoop);
2025-11-17 14:50:15 +08:00
return audio.AudioId;
2025-03-10 13:12:05 +08:00
}
private int _PlaySpeakSound(string key, GameObject posObj = null, bool isFade = false, float fadeTime = 0f, float volume = 1f)
{
if (GlobalSpeakVolume < 0.01f)
{
return -1;
}
2025-11-14 18:21:45 +08:00
var audio = _GetUsableAudio(PhxhSDK.AudioType.Sound, false);
2025-03-10 13:12:05 +08:00
//错误打印,保护
if (audio == null)
{
DebugUtil.LogError($"AudioManager, PlaySpeak By Obj, Cant GetUsableAudio key:{key}");
return -1;
}
var path = GetFullPath(key, true);
2025-03-10 13:12:05 +08:00
2025-07-28 13:02:07 +08:00
var norVol = _GetNormalizeVolume(key);
audio.SetNormalizeVolume(norVol);
2025-11-13 20:14:42 +08:00
audio.SetFollowTarget(posObj);
2025-03-10 13:12:05 +08:00
audio.SetIsSpeak(true);
if (isFade)
{
2025-11-14 18:21:45 +08:00
audio.SetVolume(0);
2025-03-10 13:12:05 +08:00
audio.PlayWithFade(path, fadeTime);
}
else
{
2025-11-14 18:21:45 +08:00
audio.SetVolume(volume * norVol);
2025-03-10 13:12:05 +08:00
audio.Play(path);
}
2025-11-14 19:10:22 +08:00
audio.SetLoop(false);
2025-03-10 13:12:05 +08:00
2025-11-17 14:50:15 +08:00
return audio.AudioId;
2025-03-10 13:12:05 +08:00
}
private int _PlaySpeakSound(string key, Vector3 pos, bool isFade = false, float fadeTime = 0f, float volume = 1f)
{
2025-11-14 18:21:45 +08:00
var audio = _GetUsableAudio(PhxhSDK.AudioType.Sound, false);
var path = GetFullPath(key, true);
2025-07-28 13:02:07 +08:00
var norVol = _GetNormalizeVolume(key);
audio.SetNormalizeVolume(norVol);
2025-11-13 20:14:42 +08:00
audio.SetPosition(pos);
2025-03-10 13:12:05 +08:00
audio.SetIsSpeak(true);
if (isFade)
{
2025-11-14 18:21:45 +08:00
audio.SetVolume(0);
2025-03-10 13:12:05 +08:00
audio.PlayWithFade(path, fadeTime);
}
else
{
2025-11-14 18:21:45 +08:00
audio.SetVolume(volume * norVol);
2025-03-10 13:12:05 +08:00
audio.Play(path);
}
2025-11-14 19:10:22 +08:00
audio.SetLoop(false);
2025-11-17 14:50:15 +08:00
return audio.AudioId;
2025-03-10 13:12:05 +08:00
}
private bool _CheckPath(string key)
{
var cfg = TableManager.Instance.Tables.AudioSourceConfig;
if (cfg.GetOrDefault(key) != null)
{
return true;
}
return false;
}
#endregion
#region API
2025-11-12 19:37:08 +08:00
public int PlayAudio(string key, AudioPlayType type, GameObject posObj = null, bool loop = false,
int priority = AudioConstant.DefaultPriority, bool isFade = false, float fadeInTime = 4f)
2025-03-10 13:12:05 +08:00
{
if (!_CheckPath(key))
{
2025-03-10 14:08:22 +08:00
if (DebugUtil.LogEnable)
{
DebugUtil.LogG($"无法找到对应音频文件key:{key}");
}
2025-03-10 13:12:05 +08:00
return -1;
}
2025-04-16 12:24:10 +08:00
if (key == Constants.Sound.ERROR_UI || key == Constants.Sound.ERROR_UI_FIGHT)
{
EventManager.Instance.Send(EventManager.EventName.Audio_ErrorAudioPlay);
}
return _PlayAudio(key, type, posObj, loop, priority, isFade, fadeInTime);
2025-03-10 13:12:05 +08:00
}
2025-11-12 19:37:08 +08:00
public int PlayAudio(string key, AudioPlayType type, Vector3 pos, bool loop = false,
int priority = AudioConstant.DefaultPriority, bool isFade = false, float fadeInTime = 4f)
2025-03-10 13:12:05 +08:00
{
if (!_CheckPath(key))
{
DebugUtil.LogG($"无法找到对应音频文件key:{key}");
return -1;
}
2025-04-16 12:24:10 +08:00
if (key == Constants.Sound.ERROR_UI || key == Constants.Sound.ERROR_UI_FIGHT)
{
EventManager.Instance.Send(EventManager.EventName.Audio_ErrorAudioPlay);
}
return _PlayAudio(key, type, pos, loop, priority, isFade, fadeInTime);
2025-03-10 13:12:05 +08:00
}
public void InitLimit(int count0, int count1, int count2)
{
MusicPoolLimit = count0;
SoundPoolLimit = count1;
SpeakPoolLimit = count2;
}
2025-11-13 16:59:52 +08:00
public AudioPlayer GetAudioByID(AudioPlayType audioType, int id)
2025-03-10 13:12:05 +08:00
{
2025-11-12 19:37:08 +08:00
if (audioType == AudioPlayType.Music)
2025-03-10 13:12:05 +08:00
{
if (_musicAudioDic.ContainsKey(id))
{
return _musicAudioDic[id];
}
if (_musicAudioLoopDic.ContainsKey(id))
{
return _musicAudioLoopDic[id];
}
return null;
}
2025-11-12 19:37:08 +08:00
if (audioType == AudioPlayType.Sound || audioType == AudioPlayType.Speak)
2025-03-10 13:12:05 +08:00
{
if (_soundAudioDic.ContainsKey(id))
{
return _soundAudioDic[id];
}
if (_soundAudioLoopDic.ContainsKey(id))
{
return _soundAudioLoopDic[id];
}
return null;
}
return null;
}
2025-11-13 16:59:52 +08:00
public AudioPlayer GetAudioByID(int id)
2025-03-10 13:12:05 +08:00
{
if (_musicAudioDic.ContainsKey(id))
{
return _musicAudioDic[id];
}
if (_musicAudioLoopDic.ContainsKey(id))
{
return _musicAudioLoopDic[id];
}
if (_soundAudioDic.ContainsKey(id))
{
return _soundAudioDic[id];
}
if (_soundAudioLoopDic.ContainsKey(id))
{
return _soundAudioLoopDic[id];
}
return null;
}
2025-11-13 16:04:30 +08:00
public void StopMusicByID(int audioID)
2025-03-10 13:12:05 +08:00
{
if (audioID >= 0)
{
if(_musicAudioDic.TryGetValue(audioID, out var audio))
{
audio.Stop();
}
if(_musicAudioLoopDic.TryGetValue(audioID, out var audioLoop))
{
audioLoop.Stop();
}
}
}
public void StopSoundByID(int audioID)
{
if (audioID >= 0)
{
if(_soundAudioDic.TryGetValue(audioID, out var audio))
{
audio.Stop();
}
if(_soundAudioLoopDic.TryGetValue(audioID, out var audioLoop))
{
audioLoop.Stop();
}
}
}
public void StopByID(int audioID)
{
if (audioID >= 0)
{
if(_musicAudioDic.TryGetValue(audioID, out var audio))
{
audio.Stop();
}
if(_musicAudioLoopDic.TryGetValue(audioID, out var audioLoop))
{
audioLoop.Stop();
}
if (_soundAudioDic.TryGetValue(audioID, out var soundAudio))
{
soundAudio.Stop();
}
if(_soundAudioLoopDic.TryGetValue(audioID, out var audioLoop1))
{
audioLoop1.Stop();
}
}
}
public void PauseAllSound()
{
foreach (var kv in _soundAudioDic)
{
var sound = kv.Value;
sound.Pause();
}
foreach (var kv in _soundAudioLoopDic)
{
var sound = kv.Value;
sound.Pause();
}
}
public void ResumeAllSound()
{
foreach (var kv in _soundAudioDic)
{
var sound = kv.Value;
sound.Resume();
}
foreach (var kv in _soundAudioLoopDic)
{
var sound = kv.Value;
sound.Resume();
}
}
2025-03-10 13:12:05 +08:00
public void StopAllMusic()
{
DebugUtil.LogG("StopAllMusic");
foreach (var kv in _musicAudioDic)
{
var audio = kv.Value;
audio.Stop();
}
foreach (var kv in _musicAudioLoopDic)
{
var audio = kv.Value;
audio.Stop();
}
}
public void StopAllSounds()
{
DebugUtil.LogG("StopAllSounds");
foreach (var kv in _soundAudioDic)
{
var audio = kv.Value;
audio.Stop();
}
foreach (var kv in _soundAudioLoopDic)
{
var audio = kv.Value;
audio.Stop();
}
}
public void StopAllSpeaks()
{
DebugUtil.LogG("StopAllSpeaks");
foreach (var kv in _soundAudioDic)
{
var audio = kv.Value;
if(audio.IsSpeak)
audio.Stop();
}
}
public void StopAll()
{
DebugUtil.LogG("StopAll");
foreach (var kv in _allAudioDic)
{
var audio = kv.Value;
audio.Stop();
}
}
public void StopWithFadeByID(int audioID, float fadeOutTime = 1f)
{
if (audioID >= 0)
{
if(_musicAudioDic.TryGetValue(audioID, out var audio))
{
2025-11-14 20:02:22 +08:00
audio.StopWithFadeOut(fadeOutTime);
2025-03-10 13:12:05 +08:00
}
if(_musicAudioLoopDic.TryGetValue(audioID, out var audioLoop))
{
2025-11-14 20:02:22 +08:00
audioLoop.StopWithFadeOut(fadeOutTime);
2025-03-10 13:12:05 +08:00
}
if (_soundAudioDic.TryGetValue(audioID, out var soundAudio))
{
2025-11-14 20:02:22 +08:00
soundAudio.StopWithFadeOut(fadeOutTime);
2025-03-10 13:12:05 +08:00
}
if(_soundAudioLoopDic.TryGetValue(audioID, out var audioLoop1))
{
2025-11-14 20:02:22 +08:00
audioLoop1.StopWithFadeOut(fadeOutTime);
2025-03-10 13:12:05 +08:00
}
}
}
public void ResumeAllMusic()
{
foreach (var kv in _musicAudioDic)
{
var audio = kv.Value;
audio.Resume();
}
foreach (var kv in _musicAudioLoopDic)
{
var audio = kv.Value;
audio.Resume();
}
}
public void AfterSwitchMainCamera(Camera camera)
{
2025-04-02 15:00:32 +08:00
//if(AudioManager.Instance.GlobalIsSpeakOpen)
2025-03-10 13:12:05 +08:00
var listener = camera.GetComponent<AudioListener>();
2025-04-02 15:00:32 +08:00
if (listener)
2025-03-10 13:12:05 +08:00
{
2025-04-02 15:00:32 +08:00
Object.DestroyImmediate(listener);
2025-03-10 13:12:05 +08:00
}
}
2025-11-14 18:21:45 +08:00
public AudioPlayer GetStoryAudioInst(PhxhSDK.AudioType audioType)
2025-03-10 13:12:05 +08:00
{
return _CreateStoryAudio(null, audioType);
2025-03-10 13:12:05 +08:00
}
public void ReleaseStoryAudios()
{
foreach (var kv in _storyAudioDic)
{
var audio = kv.Value;
audio.Stop();
Object.Destroy(audio.RootGo);
2025-11-17 14:50:15 +08:00
_allAudioDic.Remove(audio.AudioId);
2025-03-10 13:12:05 +08:00
}
_storyAudioDic.Clear();
}
2025-11-12 19:15:06 +08:00
public void PlayByKey(int audioID, string key, bool isFade = false, float fadeOutTime = 4f)
2025-03-10 13:12:05 +08:00
{
if (_allAudioDic.TryGetValue(audioID, out var audio))
{
2025-11-12 19:15:06 +08:00
var fullPath = GetFullPath(key);
2025-03-10 13:12:05 +08:00
if (isFade)
{
audio.PlayWithFade(fullPath, fadeOutTime);
2025-03-10 13:12:05 +08:00
}
else
{
audio.Play(fullPath);
2025-03-10 13:12:05 +08:00
}
}
}
2025-11-12 19:15:06 +08:00
public void PlayByKey(int audioID, string key, float fadeInTime, float targetVolume)
2025-03-10 13:12:05 +08:00
{
if (_allAudioDic.TryGetValue(audioID, out var audio))
{
2025-11-12 19:15:06 +08:00
var fullPath = GetFullPath(key);
2025-11-14 18:21:45 +08:00
audio.SetVolume(targetVolume);
audio.PlayWithFade(fullPath, fadeInTime);
2025-03-10 13:12:05 +08:00
}
}
public void ReleaseMusicAudios()
{
var musicAudioList = _musicAudioDic.ToList();
for (int i = musicAudioList.Count - 1; i >= 0; i--)
{
var kv = musicAudioList[i];
var audio = kv.Value;
var audioID = kv.Key;
audio.Stop();
_musicAudioDic.Remove(audioID);
_allAudioDic.Remove(audioID);
Object.Destroy(audio.RootGo);
}
var musicAudioLoopList = _musicAudioLoopDic.ToList();
for (int i = musicAudioLoopList.Count - 1; i >= 0; i--)
{
var kv = musicAudioLoopList[i];
var audio = kv.Value;
var audioID = kv.Key;
audio.Stop();
_musicAudioLoopDic.Remove(audioID);
_allAudioDic.Remove(audioID);
Object.Destroy(audio.RootGo);
}
_musicAudioDic.Clear();
_musicAudioLoopDic.Clear();
}
public void ReleaseSoundsAudios()
{
var soundAudioList = _soundAudioDic.ToList();
for (int i = soundAudioList.Count - 1; i >= 0; i--)
{
var kv = soundAudioList[i];
var audio = kv.Value;
var audioID = kv.Key;
audio.Stop();
_soundAudioDic.Remove(audioID);
_allAudioDic.Remove(audioID);
Object.Destroy(audio.RootGo);
}
var soundAudioLoopList = _soundAudioLoopDic.ToList();
for (int i = soundAudioLoopList.Count - 1; i >= 0; i--)
{
var kv = soundAudioLoopList[i];
var audio = kv.Value;
var audioID = kv.Key;
audio.Stop();
_soundAudioLoopDic.Remove(audioID);
_allAudioDic.Remove(audioID);
Object.Destroy(audio.RootGo);
}
_soundAudioDic.Clear();
_soundAudioLoopDic.Clear();
_playSoundTimeStampDic.Clear();
2025-03-10 13:12:05 +08:00
}
public void ReleaseAllAudios()
{
ReleaseMusicAudios();
ReleaseSoundsAudios();
2025-04-09 17:46:50 +08:00
foreach (var playTypeAudios in _playingLDic)
{
playTypeAudios.Value.Clear();
}
_allAudioDic.Clear();
2025-11-13 16:59:52 +08:00
AudioPlayer.ReleaseLoadedAssets();
2025-03-10 13:12:05 +08:00
}
2025-11-14 18:21:45 +08:00
public void Add2Playing(PhxhSDK.AudioType audioType, int id, bool isSpeak = false)
2025-03-10 13:12:05 +08:00
{
2025-11-12 19:56:26 +08:00
AudioPlayType type;
2025-11-14 18:21:45 +08:00
if (audioType == PhxhSDK.AudioType.Music)
2025-03-10 13:12:05 +08:00
{
2025-11-12 19:56:26 +08:00
type = AudioPlayType.Music;
2025-03-10 13:12:05 +08:00
}
else
{
if (isSpeak)
2025-11-12 19:56:26 +08:00
type = AudioPlayType.Speak;
2025-03-10 13:12:05 +08:00
else
{
2025-11-12 19:56:26 +08:00
type = AudioPlayType.Sound;
2025-03-10 13:12:05 +08:00
}
}
var list = _playingLDic[type];
if (!list.Contains(id))
{
list.Add(id);
}
}
2025-11-14 18:21:45 +08:00
public void RemovePlaying(PhxhSDK.AudioType audioType, int id, bool isSpeak = false)
2025-03-10 13:12:05 +08:00
{
2025-11-12 19:56:26 +08:00
AudioPlayType type;
2025-11-14 18:21:45 +08:00
if (audioType == PhxhSDK.AudioType.Music)
2025-03-10 13:12:05 +08:00
{
2025-11-12 19:56:26 +08:00
type = AudioPlayType.Music;
2025-03-10 13:12:05 +08:00
}
else
{
if (isSpeak)
2025-11-12 19:56:26 +08:00
type = AudioPlayType.Speak;
2025-03-10 13:12:05 +08:00
else
{
2025-11-12 19:56:26 +08:00
type = AudioPlayType.Sound;
2025-03-10 13:12:05 +08:00
}
}
var list = _playingLDic[type];
if (list.Contains(id))
{
list.Remove(id);
}
}
public void RemovePlaying(int id)
{
foreach (var kv in _playingLDic)
{
var list = kv.Value;
if (list.Contains(id))
{
list.Remove(id);
}
}
}
public async UniTask<float> GetClipLength(string key)
{
var path = GetFullPath(key);
var clip = await AssetManager.Instance.LoadAssetAsync<AudioClip>(path);
if (clip)
{
return clip.length;
}
return -1;
}
2025-11-14 20:02:22 +08:00
public AudioPlayer GetSoundByAudioID(int audioID)
{
2025-11-14 20:02:22 +08:00
if (_soundAudioDic.TryGetValue(audioID, out var audio))
{
2025-11-14 20:02:22 +08:00
return audio;
}
2025-11-14 20:02:22 +08:00
if (_soundAudioLoopDic.TryGetValue(audioID, out var audioLoop))
{
2025-11-14 20:02:22 +08:00
return audioLoop;
}
return null;
}
2025-03-10 13:12:05 +08:00
#endregion
2025-04-02 15:00:32 +08:00
#region Listener
private void _SetListenerPos()
{
if (AudioRoot && _isFollowCamera)
{
var camera = CameraManager.Instance.MainCamera;
2025-04-08 16:50:58 +08:00
if (camera)
{
AudioRoot.transform.position = camera.transform.position;
}
2025-04-02 15:00:32 +08:00
}
}
private void _InitListenerPos()
{
AudioRoot.transform.position = new Vector3(0, 0, 0);
}
public void EnterFollowState()
{
_isFollowCamera = true;
}
public void ExitFollowState()
{
_isFollowCamera = false;
_InitListenerPos();
}
#endregion
2025-04-16 12:24:10 +08:00
#region Events
private void _OnErrorAudioPlay()
{
foreach (var kv in _soundAudioDic)
{
var sound = kv.Value;
if (sound.IsPlaying)
{
if (sound.Clip.name == Constants.Sound.COMMON_CLAIM || sound.Clip.name == Constants.Sound.COMMON_CLICK)
{
sound.Stop();
}
}
}
}
#endregion
2025-03-10 13:12:05 +08:00
}
public struct AudioInfo
{
public bool persist;
public float volume;
public float fadeInValue;
public float fadeOutValue;
public bool isSpeak;
}