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
{
///
/// 单独分离的音频资源加载器,方便后续升级资源加载策略
///
public class AudioSourceHandler : IAudioSourceHandler
{
private static readonly Dictionary _AUDIO_PATH = new Dictionary()
{
{AudioType.BGM, "BGM"},
{AudioType.BSE, "BSE"},
{AudioType.SOUND, "SE"}
};
private readonly string _rootPath;
private Dictionary _audioSource;
private Dictionary _audioReferenceCount;
private List _audioPaths;
//用于编辑器状态下监视资源状态
public Dictionary editorLog;
public Dictionary 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();
this._audioSource = new Dictionary();
this._audioPaths =
new List(AssetManager.Instance.GetResourceLocation(this._rootPath));
#if UNITY_EDITOR
this.editorLog = new Dictionary();
#endif
}
public bool IsAsync()
{
return false;
}
///
/// 异步加载音频资源
///
///
///
///
public async Task 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(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;
}
///
/// 获取一个音频资源
///
///
///
///
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(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
}
}
}
///
/// 卸载所有未使用的音效资源
///
public void UnLoadAllInvalid()
{
List sourceKeys = new List(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;
}
}