Files
2024-10-16 00:03:41 +08:00

253 lines
8.9 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}
}