Files
taptap2024_GJ_chidouren/Assets/Scripts/System/AudioHandler/AudioSourceHandler.cs

253 lines
8.9 KiB
C#
Raw Normal View History

2024-10-16 00:03:41 +08:00
using System.Collections.Generic;
using System.Threading.Tasks;
using Audio;
using Framework.Asset;
using UnityEngine;
using YooAsset;
using AudioType = Framework.Audio.AudioType;
namespace System.AudioHandler
{
/// <summary>
/// 单独分离的音频资源加载器,方便后续升级资源加载策略
/// </summary>
public class AudioSourceHandler : IAudioSourceHandler
{
private static readonly Dictionary<AudioType, string> _AUDIO_PATH = new Dictionary<AudioType, string>()
{
{AudioType.BGM, "BGM"},
{AudioType.BSE, "BSE"},
{AudioType.SOUND, "SE"}
};
private readonly string _rootPath;
private Dictionary<string, AudioAsset> _audioSource;
private Dictionary<string, int> _audioReferenceCount;
private List<string> _audioPaths;
//用于编辑器状态下监视资源状态
public Dictionary<string, string> editorLog;
public Dictionary<string, string> EditorLog() => this.editorLog;
private string AudioFullPath(AudioType audioType, string audioName)
{
audioName = audioName.Replace("\\", "/");
return $"{this._rootPath}/{_AUDIO_PATH[audioType]}/{audioName}";
}
public AudioSourceHandler(string rootPath)
{
this._rootPath = rootPath;
this._audioReferenceCount = new Dictionary<string, int>();
this._audioSource = new Dictionary<string, AudioAsset>();
this._audioPaths =
new List<string>(AssetManager.Instance.GetResourceLocation(this._rootPath));
#if UNITY_EDITOR
this.editorLog = new Dictionary<string, string>();
#endif
}
public bool IsAsync()
{
return false;
}
/// <summary>
/// 异步加载音频资源
/// </summary>
/// <param name="audioType"></param>
/// <param name="audioName"></param>
/// <returns></returns>
public async Task<AudioClip> GetAudioClipAsync(AudioType audioType, string audioName)
{
var audioKey = audioType + audioName;
//当指定音效没有或者其资源为null时通过ab包加载
if (!this._audioSource.ContainsKey(audioKey) || this._audioSource[audioKey] == null)
{
var fullpath = AudioFullPath((AudioType) audioType, audioName);
var path = GetAudioPath(fullpath);
if (path == null)
{
return null;
}
if (!AssetManager.Instance.CheckLocationValid (path , false))
{
#if UNITY_EDITOR
Debug.Log ("【AudioManager】无效的音频资源路径" + path);
#endif
return null;
}
var audioAsset = AssetManager.Instance.LoadAssetRequestAsync<AudioClip>(path , false);
await audioAsset.Task;
this._audioSource[audioKey] = new AudioAsset(audioAsset , audioKey);
this._audioReferenceCount[audioKey] = 0;
}
var audioClip = this._audioSource[audioKey].Clip;
this._audioReferenceCount[audioKey] += audioClip != null ? 1 : 0;
#if UNITY_EDITOR
RefreshLog();
#endif
return audioClip;
}
public string GetAudioPath(string pullPath)
{
pullPath += ".";
foreach (var audioPath in this._audioPaths)
{
if (audioPath.IndexOf(pullPath, StringComparison.Ordinal) == 0)
{
return audioPath;
}
}
return null;
}
/// <summary>
/// 获取一个音频资源
/// </summary>
/// <param name="audioType"></param>
/// <param name="audioName"></param>
/// <returns></returns>
public AudioClip GetAudioClip(AudioType audioType, string audioName)
{
var audioKey = audioType + audioName;
//当指定音效没有或者其资源为null时通过ab包加载
if (!this._audioSource.ContainsKey(audioKey) || this._audioSource[audioKey] == null)
{
var fullpath = AudioFullPath((AudioType) audioType, audioName);
var path = GetAudioPath(fullpath);
if (path == null)
{
return null;
}
if (!AssetManager.Instance.CheckLocationValid (path , false))
{
// #if UNITY_EDITOR
// Debug.Log ("【AudioManager】无效的音频资源路径" + path);
// #endif
Debug.Log ("【AudioManager】无效的音频资源路径" + path);
return null;
}
var audioAsset = AssetManager.Instance.LoadAssetRequest<AudioClip>(path , false);
this._audioSource[audioKey] = new AudioAsset(audioAsset , audioKey);
this._audioReferenceCount[audioKey] = 0;
}
var audioClip = this._audioSource[audioKey].Clip;
this._audioReferenceCount[audioKey] += audioClip != null ? 1 : 0;
#if UNITY_EDITOR
RefreshLog();
#endif
return audioClip;
}
public void OnAudioInvalid(AudioType audioType, string audioName)
{
var audioKey = audioType + audioName;
if (this._audioReferenceCount.ContainsKey(audioKey) && this._audioReferenceCount[audioKey] >= 1)
{
this._audioReferenceCount[audioKey] -= 1;
if (this._audioReferenceCount[audioKey] == 0)
{
if (audioType == AudioType.BGM || audioType == AudioType.BSE)
{
var audioAsset = this._audioSource[audioKey];
this._audioSource[audioKey] = null;
audioAsset.KillAsset();
}
#if UNITY_EDITOR
RefreshLog();
#endif
}
}
}
/// <summary>
/// 卸载所有未使用的音效资源
/// </summary>
public void UnLoadAllInvalid()
{
List<string> sourceKeys = new List<string>(this._audioSource.Keys);
for (int i = sourceKeys.Count - 1; i >= 0; i--)
{
var audioSourceKey = sourceKeys[i];
if (this._audioReferenceCount[audioSourceKey] == 0)
{
// ushort group = ushort.Parse(audioSourceKey.Substring(0, 1));
// string audioName = audioSourceKey.Substring(1);
var audioAsset = this._audioSource[audioSourceKey];
audioAsset.KillAsset();
this._audioSource.Remove(audioSourceKey);
this._audioReferenceCount.Remove(audioSourceKey);
#if UNITY_EDITOR
this.editorLog.Remove(audioSourceKey);
#endif
}
}
#if UNITY_EDITOR
RefreshLog();
#endif
}
public void RefreshLog()
{
#if UNITY_EDITOR
foreach (var audioSourceKey in this._audioSource.Keys)
{
this.editorLog[audioSourceKey] =
$"\t{this._audioSource[audioSourceKey] != null} \t{this._audioReferenceCount[audioSourceKey]}";
}
#endif
}
public float[] LoadVolume()
{
var volumes = new float[3] {1, 1, 1};
volumes[0] = Account.Instance.AccountSystemData.BGMValue;
volumes[1] = Account.Instance.AccountSystemData.BSEValue;
volumes[2] = Account.Instance.AccountSystemData.SEValue;
return volumes;
}
public void SaveVolume(float bgm, float bse, float se)
{
Account.Instance.AccountSystemData.BGMValue = bgm;
Account.Instance.AccountSystemData.BSEValue = bse;
Account.Instance.AccountSystemData.SEValue = se;
Account.Instance.Save(Framework.Save.SaveData.System);
}
}
public class AudioAsset
{
private AudioClip _clip;
private AssetHandle _assetRequest;
private string _key;
public AudioAsset(AssetHandle assetRequest, string key)
{
this._assetRequest = assetRequest;
this._key = key;
if (assetRequest == null || assetRequest.AssetObject == null)
{
Debug.Log("Error Audio Path : " + key + " path: " + assetRequest?.GetAssetInfo ().AssetPath);
return;
}
this._clip = assetRequest.AssetObject as AudioClip;
}
public void KillAsset()
{
this._clip = null;
this._assetRequest.Release();
}
public string Key => this._key;
public AudioClip Clip => this._clip;
}
}