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

487 lines
12 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
2025-03-10 13:12:05 +08:00
using PhxhSDK;
using UnityEngine;
using UnityEngine.Networking;
2025-11-13 16:59:52 +08:00
public class AudioPlayer: AudioBase
2025-03-10 13:12:05 +08:00
{
2025-11-13 18:36:05 +08:00
// 静态字段已迁移到 AudioVolumeSettings 类
// 为了向后兼容,保留静态属性(委托到 AudioVolumeSettings)
public static float GlobalVolume
{
get => AudioVolumeSettings.Instance.GlobalVolume;
set => AudioVolumeSettings.Instance.GlobalVolume = value;
}
public static float GlobalMusicVolume
{
get => AudioVolumeSettings.Instance.MusicVolume;
set => AudioVolumeSettings.Instance.MusicVolume = value;
}
public static float GlobalSoundVolume
{
get => AudioVolumeSettings.Instance.SoundVolume;
set => AudioVolumeSettings.Instance.SoundVolume = value;
}
public static float GlobalSpeakVolume
{
get => AudioVolumeSettings.Instance.SpeakVolume;
set => AudioVolumeSettings.Instance.SpeakVolume = value;
}
2025-03-10 13:12:05 +08:00
2025-07-28 13:02:07 +08:00
private float normalizeVolume = 1f;
2025-04-16 17:58:35 +08:00
protected AudioSource _audioSource;
2025-03-10 13:12:05 +08:00
private bool _isSpeak;
private static long _curPlayID;
private long _playID = -1; //播放ID,越小越早
private AudioClip _clip;
private long _playTime; //最近一次播放的时间戳
public static Dictionary<string, int> LoadedPath = new();
public long playTime => _playTime;
2025-04-16 12:24:10 +08:00
public AudioClip Clip => _clip;
2025-03-10 13:12:05 +08:00
public long PlayID => _playID;
public bool IsSpeak => _isSpeak;
2025-04-16 17:58:35 +08:00
public float Volume => _audioSource.volume;
2025-11-13 18:55:54 +08:00
// 淡入淡出效果(使用独立的效果类)
private AudioFadeEffect _fadeEffect;
// 空间音效控制器(使用独立的控制器类)
private AudioSpatialController _spatialController;
2025-03-10 13:12:05 +08:00
private bool _isPlayEnd
{
get
{
if (!_audioSource || !_clip)
{
return false;
}
2025-04-03 18:38:53 +08:00
if (_audioSource.isPlaying)
2025-04-08 11:42:55 +08:00
return _audioSource.time > _clip.length;
2025-04-03 18:38:53 +08:00
else
2025-08-20 14:39:40 +08:00
return true;
2025-03-10 13:12:05 +08:00
}
}
#region Construct
2025-11-13 16:59:52 +08:00
public AudioPlayer(AudioType audioType, GameObject rootGo, GameObject posGo, AudioInfo audioInfo,
2025-03-10 13:12:05 +08:00
bool loop = false, bool is3D = false)
{
this.audioType = audioType;
_rootGo = rootGo;
_audioSource = _GetSource();
2025-11-13 18:36:05 +08:00
_audioSource.volume = AudioVolumeSettings.Instance.GlobalVolume;
2025-03-10 13:12:05 +08:00
targetVolume = 1f;
_isSpeak = audioInfo.isSpeak;
2025-11-13 18:55:54 +08:00
// 初始化淡入淡出效果
_fadeEffect = new AudioFadeEffect(fadeInDuration: 4f, fadeOutDuration: 4f);
// 初始化空间音效控制器
_spatialController = new AudioSpatialController(_rootGo.transform, _audioSource);
// 如果构造时指定了跟随对象,设置跟随
if (posGo != null)
{
_spatialController.SetFollowTarget(posGo);
}
2025-03-10 13:12:05 +08:00
}
private AudioSource _GetSource()
{
var source = _rootGo.GetComponent<AudioSource>();
if (!source)
{
source = _rootGo.AddComponent<AudioSource>();
}
return source;
}
#endregion
#region Inherit
public override void Update(float dt)
{
if (!_audioSource || !_clip)
{
return;
}
2025-11-13 18:55:54 +08:00
// 更新淡入淡出效果
bool shouldStop = _fadeEffect.Update(dt);
2025-03-10 13:12:05 +08:00
if (playState == PlayState.Playing || _audioSource.isPlaying)
{
switch (audioType)
{
case (AudioType.Music):
{
_SetMusicVolume();
break;
2025-03-10 13:12:05 +08:00
}
case (AudioType.Sound):
2025-03-10 13:12:05 +08:00
{
if (_isSpeak)
{
_SetSpeakVolume();
}
else
{
_SetSoundVolume();
}
break;
2025-03-10 13:12:05 +08:00
}
default:
2025-03-10 13:12:05 +08:00
break;
}
}
if (playState == PlayState.Paused)
{
return;
}
2025-11-13 18:55:54 +08:00
// 更新空间位置跟随
if (playState == PlayState.Playing)
2025-03-10 13:12:05 +08:00
{
_spatialController.Update();
2025-03-10 13:12:05 +08:00
}
2025-11-13 18:55:54 +08:00
// 更新播放状态
// 检查是否应该停止(播放结束或淡出完成)
if (_isPlayEnd || shouldStop || playState == PlayState.Stopped)
2025-03-10 13:12:05 +08:00
{
2025-08-20 14:39:40 +08:00
if (playState == PlayState.Loading)
return;
2025-03-10 13:12:05 +08:00
Stop();
}
}
public override void Pause()
{
_audioSource.Pause();
playState = PlayState.Paused;
}
public override void Resume()
{
_audioSource.UnPause();
playState = PlayState.Playing;
}
public override void Play(float volume = 1f)
{
playState = PlayState.Playing;
2025-11-13 18:55:54 +08:00
_fadeEffect.Stop(); // 停止任何淡入淡出效果
2025-03-10 13:12:05 +08:00
targetVolume = 1f;
_audioSource.Play();
_playID = _GenPlayID();
_playTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
2025-03-10 13:12:05 +08:00
AudioManager.Instance.AudioMgrObj.Add2Playing(audioType, audioID, _isSpeak);
}
public void PlayWithFade(float volume = 1f)
{
playState = PlayState.Playing;
_audioSource.Play();
_playID = _GenPlayID();
AudioManager.Instance.AudioMgrObj.RemovePlaying(audioType, audioID);
}
2025-11-13 18:55:54 +08:00
2025-08-20 14:39:40 +08:00
public new void Stop()
2025-03-10 13:12:05 +08:00
{
2025-11-13 18:55:54 +08:00
_fadeEffect.Stop(); // 停止淡入淡出效果
2025-04-09 17:46:50 +08:00
AudioManager.Instance.AudioMgrObj.RemovePlaying(audioType, audioID);
2025-11-13 18:55:54 +08:00
2025-03-10 13:12:05 +08:00
if (_isPlayEnd)
{
2025-04-03 18:36:30 +08:00
playState = PlayState.Stopped;
2025-03-10 13:12:05 +08:00
return;
}
2025-03-24 15:59:50 +08:00
if (_audioSource)
{
_audioSource.Stop();
}
2025-03-10 13:12:05 +08:00
base.Stop();
}
public void StopWithFade(float fadeOutTime = 1f)
{
2025-11-13 18:55:54 +08:00
_fadeEffect.StartFadeOut(fadeOutTime);
2025-03-10 13:12:05 +08:00
}
#endregion
#region Utils
private long _GenPlayID()
{
return ++_curPlayID;
}
public static void ResetPlayID()
{
_curPlayID = 0;
}
2025-08-15 13:58:07 +08:00
public AudioSource GetAudioSource()
{
return _audioSource;
}
2025-03-10 13:12:05 +08:00
private void _SetMusicVolume()
{
2025-11-13 18:36:05 +08:00
var settings = AudioVolumeSettings.Instance;
2025-11-13 18:55:54 +08:00
var fadeValue = _fadeEffect.FadeValue;
_audioSource.volume = fadeValue * settings.MusicVolume * settings.GlobalVolume * targetVolume * normalizeVolume;
2025-03-10 13:12:05 +08:00
}
private void _SetSoundVolume()
{
2025-11-13 18:36:05 +08:00
var settings = AudioVolumeSettings.Instance;
2025-11-13 18:55:54 +08:00
var fadeValue = _fadeEffect.FadeValue;
_audioSource.volume = fadeValue * settings.SoundVolume * settings.GlobalVolume * targetVolume * normalizeVolume;
2025-03-10 13:12:05 +08:00
}
private void _SetSpeakVolume()
{
2025-11-13 18:36:05 +08:00
var settings = AudioVolumeSettings.Instance;
2025-11-13 18:55:54 +08:00
var fadeValue = _fadeEffect.FadeValue;
_audioSource.volume = fadeValue * settings.SpeakVolume * settings.GlobalVolume * targetVolume * normalizeVolume;
2025-03-10 13:12:05 +08:00
}
#endregion
#region API
public void Play(string cueName, AudioInfo audioInfo, bool isLoop = false)
{
targetVolume = 1f;
2025-11-13 18:55:54 +08:00
_fadeEffect.Stop(); // 停止任何淡入淡出效果
2025-03-10 13:12:05 +08:00
playState = PlayState.Playing;
_playID = _GenPlayID();
AudioManager.Instance.AudioMgrObj.Add2Playing(audioType, audioID, _isSpeak);
}
2025-08-19 18:12:10 +08:00
public void Play(string path)
{
2025-08-20 14:39:40 +08:00
playState = PlayState.Loading;
2025-08-19 18:12:10 +08:00
PlayAsync(path);
}
private async void PlayAsync(string path)
2025-03-10 13:12:05 +08:00
{
_clip = await AssetManager.Instance.LoadAssetAsync<AudioClip>(path, null, true);
if (LoadedPath.ContainsKey(path))
{
++LoadedPath[path];
}
else
{
LoadedPath.TryAdd(path, 1);
}
2025-03-10 13:12:05 +08:00
if (!_clip)
{
playState = PlayState.Stopped;
return;
}
_audioSource.clip = _clip;
2025-08-19 18:12:10 +08:00
2025-11-13 18:55:54 +08:00
_fadeEffect.Stop(); // 停止任何淡入淡出效果
2025-03-10 13:12:05 +08:00
targetVolume = 1f;
2025-08-19 18:12:10 +08:00
2025-03-10 13:12:05 +08:00
_playID = _GenPlayID();
AudioManager.Instance.AudioMgrObj.Add2Playing(audioType, audioID, _isSpeak);
_audioSource.Play();
2025-08-20 14:39:40 +08:00
playState = PlayState.Playing;
2025-03-10 13:12:05 +08:00
}
public async void PlayWithFade(string path, float fadeInTime = 4f, float fadeOutTime = 4f)
{
_clip = await AssetManager.Instance.LoadAssetAsync<AudioClip>(path, null, true);
if (LoadedPath.ContainsKey(path))
{
++LoadedPath[path];
}
else
{
LoadedPath.TryAdd(path, 1);
}
2025-03-10 13:12:05 +08:00
if (!_clip)
{
return;
}
_audioSource.clip = _clip;
2025-11-13 18:55:54 +08:00
// 设置淡入淡出时长并启动淡入
_fadeEffect.FadeInDuration = fadeInTime;
_fadeEffect.FadeOutDuration = fadeOutTime;
_fadeEffect.StartFadeIn();
targetVolume = 1f;
2025-03-10 13:12:05 +08:00
_audioSource.volume = 0f;
playState = PlayState.Playing;
_playID = _GenPlayID();
AudioManager.Instance.AudioMgrObj.Add2Playing(audioType, audioID, _isSpeak);
_audioSource.Play();
}
/// <summary>
/// 设置是否启用 3D 空间音效
/// </summary>
2025-03-10 13:12:05 +08:00
public void SetIs3D(bool is3D = false)
{
if (is3D)
{
_spatialController.Enable3D();
}
else
{
_spatialController.Disable3D();
}
2025-03-10 13:12:05 +08:00
}
/// <summary>
/// 设置跟随对象(自动启用 3D)
/// </summary>
2025-03-10 13:12:05 +08:00
public void SetPosObj(GameObject go = null)
{
_spatialController.SetFollowTarget(go);
2025-03-10 13:12:05 +08:00
}
/// <summary>
/// 设置静态位置
/// </summary>
2025-03-10 13:12:05 +08:00
public void SetPos(Vector3 position)
{
_spatialController.SetStaticPosition(position, enable3D: true);
2025-03-10 13:12:05 +08:00
}
public void SetIsLoop(bool isLoop)
{
loop = isLoop;
_audioSource.loop = isLoop;
}
public void SetIsSpeak(bool isSpeak)
{
_isSpeak = isSpeak;
}
2025-07-28 13:02:07 +08:00
public void SetNormalizeVolume(float vol = 1f)
{
normalizeVolume = vol;
}
2025-11-13 18:55:54 +08:00
/// <summary>
/// 启动淡入效果(已弃用,建议直接使用 PlayWithFade)
/// </summary>
[System.Obsolete("Use PlayWithFade instead")]
2025-03-10 13:12:05 +08:00
public void SetIsFadeIn(bool isFadeIn)
{
2025-11-13 18:55:54 +08:00
if (isFadeIn)
{
_fadeEffect.StartFadeIn();
}
else
{
_fadeEffect.Stop();
}
2025-03-10 13:12:05 +08:00
}
public string GetCueSheetName()
{
if (_audioSource)
{
return _clip.name;
}
return "";
}
public float GetCurPlayLength()
{
if (_audioSource)
{
return _audioSource.time;
}
return -1;
}
public float GetTime()
{
if (!_audioSource)
return -1;
return _audioSource.time;
}
public static void ReleaseLoadedAssets()
{
foreach (var kv in LoadedPath)
{
var key = kv.Key;
var count = kv.Value;
while (count > 0)
{
AssetManager.Instance.Unload(key, false, true);
--count;
}
}
}
2025-11-13 16:59:52 +08:00
/// <summary>
/// 获取音频频谱数据(用于可视化)
/// </summary>
public void GetSpectrumData(float[] spectrums)
{
if (_audioSource != null)
{
_audioSource.GetSpectrumData(spectrums, 0, FFTWindow.Blackman);
}
}
2025-03-10 13:12:05 +08:00
#endregion
}
public class AudioConstant
{
/// <summary>
/// 最大音乐播放数
/// </summary>
public const int MaxMusicCount = 1;
/// <summary>
/// 最大音频播放数
/// </summary>
public const int MaxSoundCount = 100;
/// <summary>
/// 最大语音播放数
/// </summary>
public const int MaxSpeakCount = 1;
/// <summary>
/// 优先级
/// </summary>
public const int MaxPriority = 99;
public const int MinPriority = 0;
public const int DefaultPriority = 29;
public const int LowPriority = 30;
2025-03-10 13:12:05 +08:00
}