1111
This commit is contained in:
@@ -164,11 +164,7 @@ public class VideoPanel : BasePanel
|
|||||||
private void OnStopMove()
|
private void OnStopMove()
|
||||||
{
|
{
|
||||||
Debug.Log("UnityEvo:视频播放完成");
|
Debug.Log("UnityEvo:视频播放完成");
|
||||||
AudioCoreManager.SetMusicVolume(new AudioData()
|
AudioCoreManager.SetMusicVolume(2f, 1f);
|
||||||
{
|
|
||||||
fadeDuration = 2f,
|
|
||||||
volume = 1f,
|
|
||||||
});
|
|
||||||
_animator.Play("vid_maskDefault", 0, 0);
|
_animator.Play("vid_maskDefault", 0, 0);
|
||||||
if (renderTexture != null)
|
if (renderTexture != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,11 +25,7 @@ public class VideoSystem : AbstractSystem, IVideoSystem
|
|||||||
|
|
||||||
public async void PlayVideo(VideoPanel.VideoInfo info)
|
public async void PlayVideo(VideoPanel.VideoInfo info)
|
||||||
{
|
{
|
||||||
AudioCoreManager.SetMusicVolume(new AudioData()
|
AudioCoreManager.SetMusicVolume(2f, 0f);
|
||||||
{
|
|
||||||
fadeDuration = 2f,
|
|
||||||
volume = 0f,
|
|
||||||
});
|
|
||||||
await this.GetSystem<IPanelSystem>().PushQueue<VideoPanel>(parent:AppConfig.GetDefaultMainInstance().transform,packageName:"Main");
|
await this.GetSystem<IPanelSystem>().PushQueue<VideoPanel>(parent:AppConfig.GetDefaultMainInstance().transform,packageName:"Main");
|
||||||
this.GetSystem<IPanelSystem>().SendPanelEvent(ModeType.VideoStart,info);
|
this.GetSystem<IPanelSystem>().SendPanelEvent(ModeType.VideoStart,info);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using System.Collections;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Stary.Evo.AudioCore
|
namespace Stary.Evo.AudioCore
|
||||||
@@ -15,6 +17,16 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float delayTime;
|
public float delayTime;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 资源包名
|
||||||
|
/// </summary>
|
||||||
|
public string packageName;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 资源名
|
||||||
|
/// </summary>
|
||||||
|
public string assetName;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 音频
|
/// 音频
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -59,36 +71,55 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// 3D声音最大距离
|
/// 3D声音最大距离
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float audio3DMaxDistance;
|
public float audio3DMaxDistance;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 异步取消令牌
|
|
||||||
/// </summary>
|
|
||||||
public CancellationToken cancellationToken;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IAudio
|
public interface IAudio
|
||||||
{
|
{
|
||||||
|
IResources Resources { get; set; }
|
||||||
|
AudioSourcePool AudioSourcePool { get; set; }
|
||||||
|
AudioData Initialize(AudioData audioData);
|
||||||
void Play(AudioData audioData);
|
void Play(AudioData audioData);
|
||||||
|
|
||||||
void Stop(AudioData audioData);
|
UniTask PlayAsync(AudioData audioData);
|
||||||
|
UniTask FadeInMusic(AudioSource source, float fadeDuration);
|
||||||
|
UniTask FadeOutMusic(AudioSource source, float fadeDuration);
|
||||||
|
|
||||||
|
|
||||||
void Stop();
|
void Stop();
|
||||||
|
void StopAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class AbstractAudio : IAudio
|
public abstract class AbstractAudio : IAudio
|
||||||
{
|
{
|
||||||
|
public IResources Resources { get; set; }
|
||||||
|
|
||||||
|
public AudioSourcePool AudioSourcePool { get; set; }
|
||||||
public abstract void Play(AudioData audioData);
|
public abstract void Play(AudioData audioData);
|
||||||
|
|
||||||
public virtual void Stop(AudioData audioData){}
|
public abstract UniTask PlayAsync(AudioData audioData);
|
||||||
|
|
||||||
public virtual void Stop(){}
|
public abstract void StopAll();
|
||||||
|
|
||||||
|
|
||||||
|
public virtual void Stop()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractAudio(IResources resources)
|
||||||
|
{
|
||||||
|
Resources = resources;
|
||||||
|
if (!GetType().Name.Contains("Music"))
|
||||||
|
{
|
||||||
|
AudioSourcePool = new AudioSourcePool(GetType().Name, -1);
|
||||||
|
AudioSourcePool.Creation();
|
||||||
|
}
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 音频数据初始化
|
/// 音频数据初始化
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="audioData"></param>
|
/// <param name="audioData"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual AudioData AudioDataInitialize(AudioData audioData)
|
public virtual AudioData Initialize(AudioData audioData)
|
||||||
{
|
{
|
||||||
if (audioData.volume == 0)
|
if (audioData.volume == 0)
|
||||||
{
|
{
|
||||||
@@ -99,7 +130,88 @@ namespace Stary.Evo.AudioCore
|
|||||||
{
|
{
|
||||||
audioData.fadeDuration = 1f;
|
audioData.fadeDuration = 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
return audioData;
|
return audioData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 音频淡入
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
/// <param name="fadeDuration"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async UniTask FadeInMusic(AudioSource source, float fadeDuration)
|
||||||
|
{
|
||||||
|
float targetVolume = source.volume;
|
||||||
|
source.volume = 0;
|
||||||
|
|
||||||
|
while (source.volume < targetVolume)
|
||||||
|
{
|
||||||
|
source.volume += targetVolume * Time.deltaTime / fadeDuration;
|
||||||
|
await UniTask.Yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 音频淡出
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
/// <param name="fadeDuration"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async UniTask FadeOutMusic(AudioSource source, float fadeDuration)
|
||||||
|
{
|
||||||
|
if (source != null)
|
||||||
|
{
|
||||||
|
float startVolume = source.volume;
|
||||||
|
|
||||||
|
while (source.volume > 0)
|
||||||
|
{
|
||||||
|
source.volume -= startVolume * Time.deltaTime / fadeDuration;
|
||||||
|
await UniTask.Yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
source.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 播放音效的协程
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
/// <param name="delay"></param>
|
||||||
|
/// <param name="onComplete"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async UniTask PlayAudioAWait(AudioSourceToken audioSourceToken, float delay, System.Action onComplete)
|
||||||
|
{
|
||||||
|
await PlayAudioAWait(audioSourceToken, delay);
|
||||||
|
onComplete?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 播放音效的协程
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
/// <param name="delay"></param>
|
||||||
|
/// <param name="onComplete"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async UniTask PlayAudioAWait(AudioSourceToken audioSourceToken, float delay)
|
||||||
|
{
|
||||||
|
Debug.Log($"PlayAudioAWait:{GetType().Name}");
|
||||||
|
if (!GetType().Name.Contains("Voice"))
|
||||||
|
{
|
||||||
|
await UniTask.Delay(TimeSpan.FromSeconds(audioSourceToken.source.clip.length - 2f),
|
||||||
|
cancellationToken: audioSourceToken.cancellationToken.Token);
|
||||||
|
await FadeOutMusic(audioSourceToken.source, 2f);
|
||||||
|
await UniTask.Delay(TimeSpan.FromSeconds(delay),
|
||||||
|
cancellationToken: audioSourceToken.cancellationToken.Token);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await UniTask.Delay(TimeSpan.FromSeconds(audioSourceToken.source.clip.length + delay),
|
||||||
|
cancellationToken: audioSourceToken.cancellationToken.Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioSourcePool.RecycleSpawn(audioSourceToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
15
Assets/04.AudioCore/RunTime/Abstract/IResources.cs
Normal file
15
Assets/04.AudioCore/RunTime/Abstract/IResources.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Stary.Evo.AudioCore
|
||||||
|
{
|
||||||
|
public interface IResources
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 加载音频资源
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
UniTask<T> LoadAssetAsync<T>(string packageName, string assetName) where T : Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Assets/04.AudioCore/RunTime/Abstract/IResources.cs.meta
Normal file
3
Assets/04.AudioCore/RunTime/Abstract/IResources.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 376ffa6a0d374fe69c2c2e30f0f6d244
|
||||||
|
timeCreated: 1767163427
|
||||||
@@ -1,148 +1,274 @@
|
|||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
namespace Stary.Evo.AudioCore
|
namespace Stary.Evo.AudioCore
|
||||||
{
|
{
|
||||||
public class AudioSourcePool: IDisposable
|
/// <summary>
|
||||||
|
/// 对象池
|
||||||
|
/// </summary>
|
||||||
|
public interface IAudioSourcePool
|
||||||
{
|
{
|
||||||
private Dictionary<string, Queue<GameObject>> poolDict = new Dictionary<string, Queue<GameObject>>();
|
/// <summary>
|
||||||
private GameObject poolObject;
|
/// 将对象存进池里
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj"></param>
|
||||||
|
void Creation();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 对象池初始化
|
/// 从未激活池里面取对象,并放入激活池
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void PoolAwake()
|
|
||||||
{
|
|
||||||
// 检查是否已经存在一个名为"AudioSourcePool"的对象
|
|
||||||
SceneManager.sceneUnloaded += OnSceneUnloaded;
|
|
||||||
poolObject = GameObject.Find("AudioSourcePool");
|
|
||||||
if (poolObject == null)
|
|
||||||
{
|
|
||||||
// 如果不存在,创建一个新对象
|
|
||||||
poolObject = new GameObject("AudioSourcePool");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化 Voice 池(只有 1 个)
|
|
||||||
poolDict["Voice"] = new Queue<GameObject>();
|
|
||||||
CreateAudioSource("Voice");
|
|
||||||
|
|
||||||
// 初始化 Music 池(最多 2 个)
|
|
||||||
poolDict["Music"] = new Queue<GameObject>();
|
|
||||||
for (int i = 0; i < 2; i++)
|
|
||||||
{
|
|
||||||
CreateAudioSource("Music");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化 SFX 池(初始 1 个,可动态扩展)
|
|
||||||
poolDict["SFX"] = new Queue<GameObject>();
|
|
||||||
CreateAudioSource("SFX");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建对象
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">定义对象类型</param>
|
|
||||||
private void CreateAudioSource(string type)
|
|
||||||
{
|
|
||||||
GameObject newObject = new GameObject($"AudioSource_{type}");
|
|
||||||
newObject.transform.SetParent(poolObject.transform); // 将新对象作为当前对象的子对象
|
|
||||||
newObject.AddComponent<AudioSource>().playOnAwake = false; // 添加 AudioSource 组件并禁用自动播放
|
|
||||||
if (type == "Music")
|
|
||||||
{
|
|
||||||
newObject.GetComponent<AudioSource>().loop = true;
|
|
||||||
}
|
|
||||||
poolDict[type].Enqueue(newObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取对象
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type"></param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public AudioSource GetAudioSource(string type)
|
AudioSourceToken Spawn();
|
||||||
{
|
|
||||||
if (poolObject == null)
|
|
||||||
{
|
|
||||||
PoolAwake();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!poolDict.ContainsKey(type))
|
/// <summary>
|
||||||
{
|
/// 从激活池中释放对象到未激活池中
|
||||||
Debug.LogError($"UnityEvo:对象池中不存在类型: {type}");
|
/// </summary>
|
||||||
return null;
|
AudioSourceToken RecycleSpawn(AudioSourceToken source);
|
||||||
}
|
|
||||||
|
|
||||||
if (poolDict[type].Count == 0)
|
|
||||||
{
|
|
||||||
// 如果池为空,动态创建新的 GameObject(仅限 SFX 与 Voice)
|
|
||||||
if (type == "SFX" || type == "Voice")
|
|
||||||
{
|
|
||||||
CreateAudioSource(type);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"UnityEvo:对象池 {type} 已用完,无法分配新的 AudioSource");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateAudioSource(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
GameObject audioObject = poolDict[type].Dequeue();
|
|
||||||
AudioSource audioSource = audioObject.GetComponent<AudioSource>();
|
|
||||||
return audioSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 回收对象
|
/// 回收对象
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="type"></param>
|
void RecycleAll();
|
||||||
/// <param name="audioObject"></param>
|
|
||||||
public void ReturnAudioSource(string type, GameObject audioObject)
|
/// <summary>
|
||||||
{
|
/// 清空对象池
|
||||||
if (!poolDict.ContainsKey(type))
|
/// </summary>
|
||||||
{
|
void RemoveAll();
|
||||||
Debug.LogError($"UnityEvo:对象池中不存在类型: {type}");
|
|
||||||
return;
|
int GetPolLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioSource audioSource = audioObject.GetComponent<AudioSource>();
|
public class AudioSourcePool : IAudioSourcePool
|
||||||
audioSource.Stop(); // 停止播放
|
{
|
||||||
audioSource.clip = null; // 清空音频剪辑
|
private GameObject poolObject;
|
||||||
audioSource.volume = 1f; // 音量大小恢复
|
|
||||||
poolDict[type].Enqueue(audioObject); // 回收到对象池
|
/// <summary>
|
||||||
|
/// 回收对象的父物体
|
||||||
|
/// </summary>
|
||||||
|
private Transform recycle;
|
||||||
|
|
||||||
|
protected List<AudioSourceToken> activepool = new List<AudioSourceToken>();
|
||||||
|
|
||||||
|
protected Queue<AudioSourceToken> inactivepool = new Queue<AudioSourceToken>();
|
||||||
|
|
||||||
|
//没有回收的个数
|
||||||
|
protected int noRecycleCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对象池物体总数量
|
||||||
|
/// </summary>
|
||||||
|
public int poolCount = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对象池最大数量
|
||||||
|
/// </summary>
|
||||||
|
private int poolSize = 0;
|
||||||
|
|
||||||
|
public AudioSourcePool(string poolName, int poolSize)
|
||||||
|
{
|
||||||
|
this.poolSize = poolSize;
|
||||||
|
poolObject = GameObject.Find(poolName);
|
||||||
|
if (poolObject == null)
|
||||||
|
{
|
||||||
|
// 如果不存在,创建一个新对象
|
||||||
|
poolObject = new GameObject(poolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
poolObject = GameObject.Find($"recycle_{poolName}");
|
||||||
|
if (poolObject == null)
|
||||||
|
{
|
||||||
|
// 如果不存在,创建一个新对象
|
||||||
|
poolObject = new GameObject($"recycle_{poolName}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 场景销毁时清空对象池
|
/// 将对象存进池里
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="scene"></param>
|
/// <param name="obj"></param>
|
||||||
void OnSceneUnloaded(Scene scene)
|
public void Creation()
|
||||||
{
|
{
|
||||||
foreach (var pair in poolDict)
|
AudioSource source = CreatAudioSource();
|
||||||
|
if (source == null)
|
||||||
{
|
{
|
||||||
Queue<GameObject> queue = pair.Value;
|
Debug.LogErrorFormat("对象池【{0}】已达最大数量【{1}】,无法创建新对象", poolObject.name, poolSize);
|
||||||
while (queue.Count > 0)
|
return;
|
||||||
{
|
|
||||||
GameObject obj = queue.Dequeue();
|
|
||||||
if (obj != null)
|
|
||||||
{
|
|
||||||
UnityEngine.Object.Destroy(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
poolDict.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (type == "Music")
|
||||||
|
// {
|
||||||
|
// newObject.GetComponent<AudioSource>().loop = true;
|
||||||
|
// }
|
||||||
|
inactivepool.Enqueue(new AudioSourceToken(source, new CancellationTokenSource()));
|
||||||
|
|
||||||
|
noRecycleCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从未激活池里面取对象,并放入激活池
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="createIfPoolEmpty">如果为空是否new出来</param>
|
||||||
|
public AudioSourceToken Spawn()
|
||||||
|
{
|
||||||
|
AudioSourceToken audioSourceToken = null;
|
||||||
|
if (noRecycleCount > 0)
|
||||||
|
{
|
||||||
|
audioSourceToken = inactivepool.Dequeue();
|
||||||
|
audioSourceToken.source.transform.SetParent(poolObject.gameObject.transform);
|
||||||
|
noRecycleCount--;
|
||||||
|
if (audioSourceToken.source == null)
|
||||||
|
Debug.LogErrorFormat("对象池中不存在此对象【{0}】请排查代码", audioSourceToken.source);
|
||||||
|
audioSourceToken.cancellationToken = new CancellationTokenSource();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var source = CreatAudioSource();
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
Debug.LogErrorFormat("对象池【{0}】已达最大数量【{1}】,无法创建新对象", poolObject.name, poolSize);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
audioSourceToken = new AudioSourceToken(source, new CancellationTokenSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
audioSourceToken.source.transform.localPosition = Vector3.zero;
|
||||||
|
audioSourceToken.source.transform.localRotation = Quaternion.identity;
|
||||||
|
audioSourceToken.source.transform.localScale = Vector3.one;
|
||||||
|
activepool.Add(audioSourceToken);
|
||||||
|
|
||||||
|
|
||||||
|
return audioSourceToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从激活池中释放对象到未激活池中
|
||||||
|
/// </summary>
|
||||||
|
public AudioSourceToken RecycleSpawn(AudioSourceToken audioSourceToken)
|
||||||
|
{
|
||||||
|
if (audioSourceToken.source != null && activepool.Contains(audioSourceToken))
|
||||||
|
{
|
||||||
|
activepool.Remove(audioSourceToken);
|
||||||
|
inactivepool.Enqueue(audioSourceToken);
|
||||||
|
audioSourceToken.source.transform.parent = recycle;
|
||||||
|
audioSourceToken.source.Stop(); // 停止播放
|
||||||
|
audioSourceToken.source.clip = null; // 清空音频剪辑
|
||||||
|
audioSourceToken.source.volume = 1f; // 音量大小恢复
|
||||||
|
noRecycleCount++;
|
||||||
|
// 释放CancellationToken资源
|
||||||
|
audioSourceToken.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 回收所有对象
|
||||||
|
/// </summary>
|
||||||
|
public void RecycleAll()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < activepool.Count; i++)
|
||||||
|
{
|
||||||
|
RecycleSpawn(activepool[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清空对象池
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveAll()
|
||||||
|
{
|
||||||
|
noRecycleCount = 0;
|
||||||
|
poolCount = 0;
|
||||||
|
GameObject.Destroy(poolObject);
|
||||||
|
inactivepool.Clear();
|
||||||
|
GameObject.Destroy(recycle.gameObject);
|
||||||
|
for (int i = 0; i < activepool.Count; i++)
|
||||||
|
{
|
||||||
|
RecycleSpawn(activepool[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
activepool.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建一个新的AudioSource对象
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj"></param>
|
||||||
|
private AudioSource CreatAudioSource()
|
||||||
|
{
|
||||||
|
if (poolCount >= poolSize && poolSize > 0)
|
||||||
|
return null;
|
||||||
|
poolCount++;
|
||||||
|
AudioSource source = new GameObject($"{poolObject.name}_{poolCount}").AddComponent<AudioSource>();
|
||||||
|
source.gameObject.transform.SetParent(recycle);
|
||||||
|
source.transform.SetParent(poolObject.transform); // 将新对象作为当前对象的子对象
|
||||||
|
source.playOnAwake = false; // 添加 AudioSource 组件并禁用自动播放
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetPolLength()
|
||||||
|
{
|
||||||
|
return inactivepool.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AudioSourceToken
|
||||||
|
{
|
||||||
|
public AudioSource source;
|
||||||
|
public CancellationTokenSource cancellationToken;
|
||||||
|
|
||||||
|
public AudioSourceToken(AudioSource source, CancellationTokenSource cancellationToken)
|
||||||
|
{
|
||||||
|
this.source = source;
|
||||||
|
this.cancellationToken = cancellationToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加释放方法
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (poolObject != null)
|
// 使用局部变量避免多线程环境下的竞态条件
|
||||||
|
var cts = Interlocked.Exchange(ref cancellationToken, null);
|
||||||
|
if (cts != null)
|
||||||
{
|
{
|
||||||
GameObject.Destroy(poolObject);
|
try
|
||||||
|
{
|
||||||
|
// 取消令牌,触发注册的回调
|
||||||
|
cts.Cancel();
|
||||||
|
cts.Dispose();
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
// 已经被释放,无需处理
|
||||||
|
}
|
||||||
|
catch (AggregateException ex)
|
||||||
|
{
|
||||||
|
// 处理注册回调抛出的异常
|
||||||
|
// 只记录第一个异常,避免日志过于冗长
|
||||||
|
Debug.LogError($"CancellationTokenSource.Cancel() 回调抛出异常: {ex.InnerExceptions[0]}");
|
||||||
|
// 可以选择不重新抛出,避免中断释放流程
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError($"CancellationTokenSource.Cancel() 抛出异常: {ex}");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// 确保始终释放资源
|
||||||
|
try
|
||||||
|
{
|
||||||
|
cts.Dispose();
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
// 已经被释放,无需处理
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
poolDict.Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,3 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: a03bd7e1c53a64843bdc29b9bd9c5bb6
|
guid: 1fdac552e09c46afb9a4116d1ce2fb8e
|
||||||
MonoImporter:
|
timeCreated: 1767150802
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Internal;
|
|
||||||
|
|
||||||
namespace Stary.Evo.AudioCore
|
|
||||||
{
|
|
||||||
// 音频协程启动器
|
|
||||||
public class CoroutineHelper : IDisposable
|
|
||||||
{
|
|
||||||
private static CoroutineHelper _instance = new CoroutineHelper();
|
|
||||||
public static CoroutineHelper Instance => _instance;
|
|
||||||
private CoroutineRunner _coroutineRunner;
|
|
||||||
|
|
||||||
private CoroutineHelper()
|
|
||||||
{
|
|
||||||
GameObject runnerObject = new GameObject("CoroutineRunner");
|
|
||||||
_coroutineRunner= runnerObject.AddComponent<CoroutineRunner>();
|
|
||||||
}
|
|
||||||
public Coroutine StartCoroutine(IEnumerator coroutine)
|
|
||||||
{
|
|
||||||
Coroutine myCoroutine = _coroutineRunner.StartIEnumerator(coroutine);
|
|
||||||
return myCoroutine;
|
|
||||||
}
|
|
||||||
public void StopCoroutine(Coroutine myCoroutine)
|
|
||||||
{
|
|
||||||
_coroutineRunner.StopIEnumerator(myCoroutine);
|
|
||||||
}
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (_coroutineRunner != null)
|
|
||||||
{
|
|
||||||
GameObject.Destroy(_coroutineRunner.gameObject);
|
|
||||||
_coroutineRunner = null;
|
|
||||||
}
|
|
||||||
if (CoroutineHelper.Instance != null)
|
|
||||||
{
|
|
||||||
CoroutineHelper._instance = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CoroutineRunner : MonoBehaviour
|
|
||||||
{
|
|
||||||
public Coroutine StartIEnumerator(IEnumerator coroutine)
|
|
||||||
{
|
|
||||||
Coroutine myCoroutine = StartCoroutine(coroutine);
|
|
||||||
return myCoroutine;
|
|
||||||
}
|
|
||||||
public void StopIEnumerator(Coroutine myCoroutine)
|
|
||||||
{
|
|
||||||
StopCoroutine(myCoroutine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 6f7491906db8d634a8aa1655c3b5621a
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,19 +1,29 @@
|
|||||||
using System.Collections;
|
using System;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace Stary.Evo.AudioCore
|
namespace Stary.Evo.AudioCore
|
||||||
{
|
{
|
||||||
public class MusicPlayer : AbstractAudio
|
public class MusicPlayer : AbstractAudio, IDisposable
|
||||||
{
|
{
|
||||||
private AudioSourcePool audioSourcePool;
|
private GameObject poolObject;
|
||||||
private AudioSource audioSource1;
|
private AudioSource audioSource1;
|
||||||
private AudioSource audioSource2;
|
private AudioSource audioSource2;
|
||||||
private AudioSource currentAudioSource;
|
private AudioSource currentAudioSource;
|
||||||
private Coroutine myCoroutine;
|
private Coroutine myCoroutine;
|
||||||
|
|
||||||
public MusicPlayer(AudioSourcePool audioSourcePool)
|
public MusicPlayer(IResources resources) : base(resources)
|
||||||
{
|
{
|
||||||
this.audioSourcePool = audioSourcePool;
|
poolObject = GameObject.Find(GetType().Name);
|
||||||
|
if (poolObject == null)
|
||||||
|
{
|
||||||
|
// 如果不存在,创建一个新对象
|
||||||
|
poolObject = new GameObject(GetType().Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
audioSource1 = CreatAudioSource("audioSource1", out AudioSource source1);
|
||||||
|
audioSource2 = CreatAudioSource("audioSource2", out AudioSource source2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -21,12 +31,37 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="audioData">{[clip:音频], [volume:音量], [fadeDuration:自然过渡时间],
|
/// <param name="audioData">{[clip:音频], [volume:音量], [fadeDuration:自然过渡时间],
|
||||||
/// [is3DAudio:是否3D音频], [audio3DPosition:3D音频位置], [audio3DMaxDistance:3D音频最大距离]}</param>
|
/// [is3DAudio:是否3D音频], [audio3DPosition:3D音频位置], [audio3DMaxDistance:3D音频最大距离]}</param>
|
||||||
public override void Play(AudioData audioData)
|
public override async void Play(AudioData audioData)
|
||||||
{
|
{
|
||||||
audioData = AudioDataInitialize(audioData);
|
if (Resources == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("AudioCoreManager: Resources is null, please initialize it first.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
audioData = Initialize(audioData);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(audioData.packageName) && !string.IsNullOrEmpty(audioData.packageName))
|
||||||
|
{
|
||||||
|
var clip = await Resources.LoadAssetAsync<AudioClip>(audioData.packageName, audioData.assetName);
|
||||||
|
if (clip == null)
|
||||||
|
{
|
||||||
|
Debug.LogErrorFormat($"从资源包【{audioData.packageName}】加载音频片段【{audioData.assetName}】失败");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
audioData.clip = clip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audioData.clip == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("播放的音效音频片段为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (audioSource1 == null)
|
if (audioSource1 == null)
|
||||||
{
|
{
|
||||||
audioSource1 = audioSourcePool.GetAudioSource("Music");
|
|
||||||
audioSource1.clip = audioData.clip;
|
audioSource1.clip = audioData.clip;
|
||||||
audioSource1.volume = audioData.volume;
|
audioSource1.volume = audioData.volume;
|
||||||
|
|
||||||
@@ -62,7 +97,6 @@ namespace Stary.Evo.AudioCore
|
|||||||
{
|
{
|
||||||
if (audioSource2 == null)
|
if (audioSource2 == null)
|
||||||
{
|
{
|
||||||
audioSource2 = audioSourcePool.GetAudioSource("Music");
|
|
||||||
audioSource2.clip = audioData.clip;
|
audioSource2.clip = audioData.clip;
|
||||||
audioSource2.volume = audioData.volume;
|
audioSource2.volume = audioData.volume;
|
||||||
|
|
||||||
@@ -99,33 +133,27 @@ namespace Stary.Evo.AudioCore
|
|||||||
Debug.LogWarning("UnityEvo:已同时存在两个背景乐在切换");
|
Debug.LogWarning("UnityEvo:已同时存在两个背景乐在切换");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override UniTask PlayAsync(AudioData audioData)
|
||||||
|
{
|
||||||
|
return UniTask.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void StopAll()
|
||||||
|
{
|
||||||
|
FadeAllMusic();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 关闭背景音乐
|
/// 关闭背景音乐
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="audioData">{[fadeDuration:自然过渡时间]}</param>
|
/// <param name="audioData">{[fadeDuration:自然过渡时间]}</param>
|
||||||
public override void Stop(AudioData audioData)
|
public override void Stop()
|
||||||
{
|
{
|
||||||
FadeAllMusic();
|
FadeAllMusic();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置背景音乐音量
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="audioData"></param>
|
|
||||||
public void SetMusicVolume(AudioData audioData)
|
|
||||||
{
|
|
||||||
if(currentAudioSource == null) return;
|
|
||||||
|
|
||||||
if (myCoroutine != null)
|
|
||||||
{
|
|
||||||
CoroutineHelper.Instance.StopCoroutine(myCoroutine);
|
|
||||||
myCoroutine = null;
|
|
||||||
}
|
|
||||||
myCoroutine = CoroutineHelper.Instance.StartCoroutine(SetMusicVolume(audioData.fadeDuration, audioData.volume));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置自然过渡到指定音量
|
/// 设置自然过渡到指定音量
|
||||||
@@ -133,25 +161,26 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// <param name="fadeDuration"></param>
|
/// <param name="fadeDuration"></param>
|
||||||
/// <param name="targetVolume"></param>
|
/// <param name="targetVolume"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private IEnumerator SetMusicVolume(float fadeDuration, float targetVolume)
|
public async UniTask SetMusicVolume(float fadeDuration, float targetVolume)
|
||||||
{
|
{
|
||||||
float startVolume = currentAudioSource.volume;
|
float startVolume = currentAudioSource.volume;
|
||||||
while (currentAudioSource.volume != targetVolume)
|
while (!Mathf.Approximately(currentAudioSource.volume, targetVolume))
|
||||||
{
|
{
|
||||||
if (currentAudioSource.volume > targetVolume)
|
if (currentAudioSource.volume > targetVolume)
|
||||||
{
|
{
|
||||||
currentAudioSource.volume -= (startVolume-targetVolume) * Time.deltaTime / fadeDuration;
|
currentAudioSource.volume -= (startVolume - targetVolume) * Time.deltaTime / fadeDuration;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
currentAudioSource.volume += (targetVolume-startVolume) * Time.deltaTime / fadeDuration;
|
currentAudioSource.volume += (targetVolume - startVolume) * Time.deltaTime / fadeDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Mathf.Abs(currentAudioSource.volume - targetVolume) < 0.01f)
|
if (Mathf.Abs(currentAudioSource.volume - targetVolume) < 0.01f)
|
||||||
{
|
{
|
||||||
currentAudioSource.volume = targetVolume;
|
currentAudioSource.volume = targetVolume;
|
||||||
}
|
}
|
||||||
yield return null;
|
|
||||||
|
await UniTask.Yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,78 +193,39 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private void FadeMusic(AudioSource source1, float fadeDuration, AudioSource source2 = null)
|
private void FadeMusic(AudioSource source1, float fadeDuration, AudioSource source2 = null)
|
||||||
{
|
{
|
||||||
CoroutineHelper.Instance.StartCoroutine(FadeInMusic(source1, fadeDuration));
|
FadeInMusic(source1, fadeDuration);
|
||||||
|
FadeOutMusic(source2, fadeDuration);
|
||||||
if (source2 != null)
|
|
||||||
{
|
|
||||||
CoroutineHelper.Instance.StartCoroutine(FadeOutMusic(source2, fadeDuration));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 关闭音频的协程
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="source"></param>
|
|
||||||
/// <param name="fadeDuration"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private IEnumerator FadeOutMusic(AudioSource source, float fadeDuration)
|
|
||||||
{
|
|
||||||
if (source == null) yield break;
|
|
||||||
float startVolume = source.volume;
|
|
||||||
|
|
||||||
while (source.volume > 0)
|
|
||||||
{
|
|
||||||
source.volume -= startVolume * Time.deltaTime / fadeDuration;
|
|
||||||
yield return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
source.Stop();
|
|
||||||
if (audioSource1 == source)
|
|
||||||
{
|
|
||||||
audioSource1 = null;
|
|
||||||
}
|
|
||||||
else if (audioSource2 == source)
|
|
||||||
{
|
|
||||||
audioSource2 = null;
|
|
||||||
}
|
|
||||||
audioSourcePool.ReturnAudioSource("Music", source.gameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FadeAllMusic()
|
private void FadeAllMusic()
|
||||||
{
|
{
|
||||||
if (currentAudioSource != null && currentAudioSource.isPlaying)
|
|
||||||
{
|
|
||||||
if (currentAudioSource == audioSource1)
|
|
||||||
{
|
|
||||||
audioSource1 = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
audioSource2 = null;
|
|
||||||
}
|
|
||||||
audioSourcePool.ReturnAudioSource("Music", currentAudioSource.gameObject);
|
|
||||||
currentAudioSource = null;
|
currentAudioSource = null;
|
||||||
}
|
|
||||||
|
|
||||||
|
audioSource1.Stop();
|
||||||
|
audioSource2.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 开启音频的协程
|
/// 创建一个新的AudioSource对象
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="source"></param>
|
/// <param name="obj"></param>
|
||||||
/// <param name="fadeDuration"></param>
|
private AudioSource CreatAudioSource(string name, out AudioSource source)
|
||||||
/// <returns></returns>
|
|
||||||
private IEnumerator FadeInMusic(AudioSource source, float fadeDuration)
|
|
||||||
{
|
{
|
||||||
float targetVolume = source.volume;
|
source = new GameObject(name).AddComponent<AudioSource>();
|
||||||
source.volume = 0;
|
source.gameObject.transform.SetParent(poolObject.transform);
|
||||||
|
source.transform.SetParent(poolObject.transform); // 将新对象作为当前对象的子对象
|
||||||
while (source.volume < targetVolume)
|
source.playOnAwake = false; // 添加 AudioSource 组件并禁用自动播放
|
||||||
{
|
return source;
|
||||||
source.volume += targetVolume * Time.deltaTime / fadeDuration;
|
|
||||||
yield return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
FadeAllMusic();
|
||||||
|
Object.Destroy(audioSource1.gameObject);
|
||||||
|
Object.Destroy(audioSource2.gameObject);
|
||||||
|
audioSource1 = null;
|
||||||
|
audioSource2 = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,15 @@
|
|||||||
using System.Collections;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Stary.Evo.AudioCore
|
namespace Stary.Evo.AudioCore
|
||||||
{
|
{
|
||||||
public class SFXPlayer : AbstractAudio
|
public class SFXPlayer : AbstractAudio, IDisposable
|
||||||
{
|
{
|
||||||
private AudioSourcePool audioSourcePool;
|
public SFXPlayer(IResources resources) : base(resources)
|
||||||
private List<AudioSource> activeSources = new List<AudioSource>(); // 正在播放的 AudioSource 列表
|
|
||||||
|
|
||||||
public SFXPlayer(AudioSourcePool audioSourcePool)
|
|
||||||
{
|
{
|
||||||
this.audioSourcePool = audioSourcePool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -20,18 +18,57 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// <param name="audioData">{[clip:音频], [volume:音量],
|
/// <param name="audioData">{[clip:音频], [volume:音量],
|
||||||
/// [onComplete:回调行为], [delayOnCompleteTime:延迟回调执行的时间],
|
/// [onComplete:回调行为], [delayOnCompleteTime:延迟回调执行的时间],
|
||||||
/// [is3DAudio:是否3D音频], [audio3DPosition:3D音频位置], [audio3DMaxDistance:3D音频最大距离]}</param>
|
/// [is3DAudio:是否3D音频], [audio3DPosition:3D音频位置], [audio3DMaxDistance:3D音频最大距离]}</param>
|
||||||
public override void Play(AudioData audioData)
|
public override async void Play(AudioData audioData)
|
||||||
{
|
{
|
||||||
audioData = AudioDataInitialize(audioData);
|
AudioSourceToken audioSourceToken = await PlayAudio(audioData);
|
||||||
|
// 使用协程处理延迟和回调
|
||||||
|
PlayAudioAWait(audioSourceToken, audioData.delayOnCompleteTime,
|
||||||
|
audioData.onComplete);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async UniTask PlayAsync(AudioData audioData)
|
||||||
|
{
|
||||||
|
AudioSourceToken audioSourceToken = await PlayAudio(audioData);
|
||||||
|
await PlayAudioAWait(audioSourceToken, audioData.delayOnCompleteTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async UniTask<AudioSourceToken> PlayAudio(AudioData audioData)
|
||||||
|
{
|
||||||
|
if (Resources == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("AudioCoreManager: Resources is null, please initialize it first.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
audioData = Initialize(audioData);
|
||||||
|
if (!string.IsNullOrEmpty(audioData.packageName) && !string.IsNullOrEmpty(audioData.packageName))
|
||||||
|
{
|
||||||
|
var clip = await Resources.LoadAssetAsync<AudioClip>(audioData.packageName, audioData.assetName);
|
||||||
|
if (clip == null)
|
||||||
|
{
|
||||||
|
Debug.LogErrorFormat($"从资源包【{audioData.packageName}】加载音频片段【{audioData.assetName}】失败");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
audioData.clip = clip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (audioData.clip == null)
|
if (audioData.clip == null)
|
||||||
{
|
{
|
||||||
Debug.LogError("播放的音效音频片段为空");
|
Debug.LogError("播放的音效音频片段为空");
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioSource source = audioSourcePool.GetAudioSource("SFX");
|
AudioSourceToken audioSourceToken = AudioSourcePool.Spawn();
|
||||||
if (source == null) return;
|
if (audioSourceToken == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("音效池为空,无法播放音效");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioSource source = audioSourceToken.source;
|
||||||
source.clip = audioData.clip;
|
source.clip = audioData.clip;
|
||||||
source.volume = audioData.volume;
|
source.volume = audioData.volume;
|
||||||
|
|
||||||
@@ -58,46 +95,27 @@ namespace Stary.Evo.AudioCore
|
|||||||
source.minDistance = 1f;
|
source.minDistance = 1f;
|
||||||
source.maxDistance = 500f;
|
source.maxDistance = 500f;
|
||||||
}
|
}
|
||||||
|
|
||||||
source.Play();
|
source.Play();
|
||||||
|
return audioSourceToken;
|
||||||
// 将 AudioSource 加入活动列表
|
|
||||||
activeSources.Add(source);
|
|
||||||
|
|
||||||
// 使用协程处理延迟和回调
|
|
||||||
CoroutineHelper.Instance.StartCoroutine(PlaySFXCoroutine(source, audioData.delayOnCompleteTime, audioData.onComplete));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 停止所有音效
|
/// 停止所有音效
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="audioData">{[无可使用变量]}</param>
|
|
||||||
public override void Stop()
|
public override void Stop()
|
||||||
{
|
{
|
||||||
if (activeSources == null) return;
|
AudioSourcePool.RecycleAll();
|
||||||
foreach (var source in activeSources)
|
|
||||||
{
|
|
||||||
if (source.isPlaying)
|
|
||||||
{
|
|
||||||
source.Stop();
|
|
||||||
audioSourcePool.ReturnAudioSource("SFX", source.gameObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
activeSources.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public override void StopAll()
|
||||||
/// 播放音效的协程
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="source"></param>
|
|
||||||
/// <param name="delay"></param>
|
|
||||||
/// <param name="onComplete"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private IEnumerator PlaySFXCoroutine(AudioSource source, float delay, System.Action onComplete)
|
|
||||||
{
|
{
|
||||||
yield return new WaitForSeconds(source.clip.length + delay);
|
AudioSourcePool.RecycleAll();
|
||||||
audioSourcePool.ReturnAudioSource("SFX", source.gameObject);
|
}
|
||||||
onComplete?.Invoke();
|
|
||||||
activeSources.Remove(source);
|
public void Dispose()
|
||||||
|
{
|
||||||
|
AudioSourcePool.RecycleAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,19 +2,17 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Stary.Evo.AudioCore
|
namespace Stary.Evo.AudioCore
|
||||||
{
|
{
|
||||||
public class VoicePlayer : AbstractAudio
|
public class VoicePlayer : AbstractAudio, IDisposable
|
||||||
{
|
{
|
||||||
private AudioSourcePool audioSourcePool;
|
private AudioSourceToken currentSource;
|
||||||
private AudioSource currentSource;
|
|
||||||
private Coroutine myCoroutine;
|
public VoicePlayer(IResources resources) : base(resources)
|
||||||
private CancellationTokenSource cancelTokenSource;
|
|
||||||
public VoicePlayer(AudioSourcePool audioSourcePool)
|
|
||||||
{
|
{
|
||||||
this.audioSourcePool = audioSourcePool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -24,80 +22,12 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// [onComplete:回调行为], [delayOnCompleteTime:延迟回调执行的时间],
|
/// [onComplete:回调行为], [delayOnCompleteTime:延迟回调执行的时间],
|
||||||
/// [is3DAudio:是否3D音频], [audio3DPosition:3D音频位置],
|
/// [is3DAudio:是否3D音频], [audio3DPosition:3D音频位置],
|
||||||
/// [audio3DMaxDistance:3D音频最大距离]}</param>
|
/// [audio3DMaxDistance:3D音频最大距离]}</param>
|
||||||
public override void Play(AudioData audioData)
|
public override async void Play(AudioData audioData)
|
||||||
{
|
{
|
||||||
// 停止当前正在播放的语音与旧协程,或旧异步
|
AudioSourceToken audioSourceToken = await PlayAudio(audioData);
|
||||||
Stop();
|
|
||||||
|
|
||||||
audioData = AudioDataInitialize(audioData);
|
|
||||||
|
|
||||||
if (myCoroutine != null)
|
|
||||||
{
|
|
||||||
CoroutineHelper.Instance.StopCoroutine(myCoroutine);
|
|
||||||
myCoroutine = null;
|
|
||||||
}
|
|
||||||
currentSource = audioSourcePool.GetAudioSource("Voice");
|
|
||||||
if (currentSource == null) return;
|
|
||||||
|
|
||||||
currentSource.clip = audioData.clip;
|
|
||||||
currentSource.volume = audioData.volume;
|
|
||||||
|
|
||||||
// 设置2D与3D音频
|
|
||||||
if (audioData.is3DAudio)
|
|
||||||
{
|
|
||||||
currentSource.transform.position = audioData.audio3DPosition;
|
|
||||||
currentSource.spatialBlend = 1;
|
|
||||||
currentSource.minDistance = 1f;
|
|
||||||
if (audioData.audio3DMaxDistance != 0)
|
|
||||||
{
|
|
||||||
currentSource.maxDistance = audioData.audio3DMaxDistance;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 默认3D最大距离为3米
|
|
||||||
currentSource.maxDistance = 3f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
currentSource.transform.position = Vector3.zero;
|
|
||||||
currentSource.spatialBlend = 0;
|
|
||||||
currentSource.minDistance = 1f;
|
|
||||||
currentSource.maxDistance = 500f;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentSource.Play();
|
|
||||||
|
|
||||||
// 使用协程处理延迟和回调
|
// 使用协程处理延迟和回调
|
||||||
myCoroutine = CoroutineHelper.Instance.StartCoroutine(PlayVoiceCoroutine(currentSource, audioData.delayOnCompleteTime, audioData.onComplete));
|
PlayAudioAWait(audioSourceToken,
|
||||||
}
|
audioData.delayOnCompleteTime, audioData.onComplete);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 停止语音
|
|
||||||
/// </summary>
|
|
||||||
/// /// <param name="audioData">{[无可使用变量]}</param>
|
|
||||||
public override void Stop()
|
|
||||||
{
|
|
||||||
// 停止当前协程
|
|
||||||
if (currentSource != null && currentSource.isPlaying)
|
|
||||||
{
|
|
||||||
currentSource.Stop();
|
|
||||||
audioSourcePool.ReturnAudioSource("Voice", currentSource.gameObject);
|
|
||||||
currentSource = null;
|
|
||||||
if (myCoroutine != null)
|
|
||||||
{
|
|
||||||
CoroutineHelper.Instance.StopCoroutine(myCoroutine);
|
|
||||||
myCoroutine = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 停掉异步任务
|
|
||||||
if (cancelTokenSource != null && cancelTokenSource.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
cancelTokenSource .Cancel();
|
|
||||||
cancelTokenSource.Dispose();
|
|
||||||
cancelTokenSource = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -108,59 +38,108 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// [is3DAudio:是否3D音频], [audio3DPosition:3D音频位置],
|
/// [is3DAudio:是否3D音频], [audio3DPosition:3D音频位置],
|
||||||
/// [audio3DMaxDistance:3D音频最大距离],
|
/// [audio3DMaxDistance:3D音频最大距离],
|
||||||
/// [cancellationToken:异步取消令牌]}</param>
|
/// [cancellationToken:异步取消令牌]}</param>
|
||||||
public async Task PlayAsync(AudioData audioData)
|
public override async UniTask PlayAsync(AudioData audioData)
|
||||||
{
|
{
|
||||||
|
AudioSourceToken audioSourceToken = await PlayAudio(audioData);
|
||||||
|
await PlayAudioAWait(audioSourceToken, audioData.delayOnCompleteTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async UniTask<AudioSourceToken> PlayAudio(AudioData audioData)
|
||||||
|
{
|
||||||
|
if (Resources == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("AudioCoreManager: Resources is null, please initialize it first.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// 停止当前正在播放的语音与旧协程,或旧异步
|
// 停止当前正在播放的语音与旧协程,或旧异步
|
||||||
Stop();
|
Stop();
|
||||||
audioData = AudioDataInitialize(audioData);
|
audioData = Initialize(audioData);
|
||||||
currentSource = audioSourcePool.GetAudioSource("Voice");
|
if (!string.IsNullOrEmpty(audioData.packageName) && !string.IsNullOrEmpty(audioData.packageName))
|
||||||
if (currentSource == null) return;
|
{
|
||||||
|
var clip = await Resources.LoadAssetAsync<AudioClip>(audioData.packageName, audioData.assetName);
|
||||||
|
if (clip == null)
|
||||||
|
{
|
||||||
|
Debug.LogErrorFormat($"从资源包【{audioData.packageName}】加载音频片段【{audioData.assetName}】失败");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
audioData.clip = clip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
currentSource.clip = audioData.clip;
|
if (audioData.clip == null)
|
||||||
currentSource.volume = audioData.volume;
|
{
|
||||||
|
Debug.LogError("播放的音效音频片段为空");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AudioSourceToken audioSourceToken = AudioSourcePool.Spawn();
|
||||||
|
if (audioSourceToken == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("音效池为空,无法播放音效");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSource = audioSourceToken;
|
||||||
|
|
||||||
|
currentSource.source.clip = audioData.clip;
|
||||||
|
currentSource.source.volume = audioData.volume;
|
||||||
|
|
||||||
// 设置2D与3D音频
|
// 设置2D与3D音频
|
||||||
if (audioData.is3DAudio)
|
if (audioData.is3DAudio)
|
||||||
{
|
{
|
||||||
currentSource.transform.position = audioData.audio3DPosition;
|
currentSource.source.transform.position = audioData.audio3DPosition;
|
||||||
currentSource.spatialBlend = 1;
|
currentSource.source.spatialBlend = 1;
|
||||||
currentSource.minDistance = 1f;
|
currentSource.source.minDistance = 1f;
|
||||||
if (audioData.audio3DMaxDistance != 0)
|
if (audioData.audio3DMaxDistance != 0)
|
||||||
{
|
{
|
||||||
currentSource.maxDistance = audioData.audio3DMaxDistance;
|
currentSource.source.maxDistance = audioData.audio3DMaxDistance;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 默认3D最大距离为3米
|
// 默认3D最大距离为3米
|
||||||
currentSource.maxDistance = 3f;
|
currentSource.source.maxDistance = 3f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
currentSource.transform.position = Vector3.zero;
|
currentSource.source.transform.position = Vector3.zero;
|
||||||
currentSource.spatialBlend = 0;
|
currentSource.source.spatialBlend = 0;
|
||||||
currentSource.minDistance = 1f;
|
currentSource.source.minDistance = 1f;
|
||||||
currentSource.maxDistance = 500f;
|
currentSource.source.maxDistance = 500f;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentSource.Play();
|
currentSource.source.Play();
|
||||||
await Task.Delay(TimeSpan.FromSeconds(audioData.clip.length), audioData.cancellationToken);
|
|
||||||
|
return audioSourceToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 播放语音的协程
|
/// 停止语音
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="source"></param>
|
/// /// <param name="audioData">{[无可使用变量]}</param>
|
||||||
/// <param name="delayOnComplete"></param>
|
public override void Stop()
|
||||||
/// <param name="onComplete"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private IEnumerator PlayVoiceCoroutine(AudioSource source, float delayOnComplete, System.Action onComplete)
|
|
||||||
{
|
{
|
||||||
yield return new WaitForSeconds(source.clip.length + delayOnComplete);
|
// 停止当前协程
|
||||||
audioSourcePool.ReturnAudioSource("Voice", source.gameObject);
|
if (currentSource != null && currentSource.source.isPlaying)
|
||||||
onComplete?.Invoke();
|
{
|
||||||
|
currentSource.source.Stop();
|
||||||
|
AudioSourcePool.RecycleSpawn(currentSource);
|
||||||
currentSource = null;
|
currentSource = null;
|
||||||
myCoroutine = null;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void StopAll()
|
||||||
|
{
|
||||||
|
AudioSourcePool.RecycleAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
AudioSourcePool.RecycleAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,23 +2,25 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
namespace Stary.Evo.AudioCore
|
namespace Stary.Evo.AudioCore
|
||||||
{
|
{
|
||||||
public static class AudioCoreManager
|
public static class AudioCoreManager
|
||||||
{
|
{
|
||||||
private static AudioSourcePool audioSourcePool;
|
private static IAudio Voice;
|
||||||
private static VoicePlayer Voice;
|
private static IAudio SFX;
|
||||||
private static SFXPlayer SFX;
|
|
||||||
private static MusicPlayer Music;
|
private static MusicPlayer Music;
|
||||||
|
private static IResources Resources;
|
||||||
|
|
||||||
public static void Initialize()
|
public static void Initialize(IResources resources)
|
||||||
{
|
{
|
||||||
audioSourcePool = new AudioSourcePool();
|
|
||||||
// 初始化播放器
|
// 初始化播放器
|
||||||
Voice = new VoicePlayer(audioSourcePool);
|
Resources = resources;
|
||||||
SFX = new SFXPlayer(audioSourcePool);
|
Voice = new VoicePlayer(Resources);
|
||||||
Music = new MusicPlayer(audioSourcePool);
|
SFX = new SFXPlayer(Resources);
|
||||||
|
Music = new MusicPlayer(Resources);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 语音
|
#region 语音
|
||||||
@@ -32,8 +34,12 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// [audio3DMaxDistance:3D音频最大距离]}</param>
|
/// [audio3DMaxDistance:3D音频最大距离]}</param>
|
||||||
public static void PlayVoice(AudioData audioData)
|
public static void PlayVoice(AudioData audioData)
|
||||||
{
|
{
|
||||||
if(Voice == null) Initialize();
|
if (Voice == null)
|
||||||
Voice.Play(audioData);
|
{
|
||||||
|
Debug.LogError("AudioCoreManager: Voice is null, please initialize it first.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Voice?.Play(audioData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -45,9 +51,13 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// [audio3DMaxDistance:3D音频最大距离],
|
/// [audio3DMaxDistance:3D音频最大距离],
|
||||||
/// [cancellationToken:异步取消令牌]}</param>
|
/// [cancellationToken:异步取消令牌]}</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static Task PlayAsyncVoice(AudioData audioData)
|
public static UniTask PlayAsyncVoice(AudioData audioData)
|
||||||
{
|
{
|
||||||
if(Voice == null) Initialize();
|
if (Voice == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("AudioCoreManager: Voice is null, please initialize it first.");
|
||||||
|
return UniTask.CompletedTask;
|
||||||
|
}
|
||||||
return Voice.PlayAsync(audioData);
|
return Voice.PlayAsync(audioData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +66,11 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static void StopVoice()
|
public static void StopVoice()
|
||||||
{
|
{
|
||||||
if(Voice == null) return;
|
if (Voice == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("AudioCoreManager: Voice is null, please initialize it first.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
Voice.Stop();
|
Voice.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +87,11 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// [audio3DMaxDistance:3D音频最大距离]}</param>
|
/// [audio3DMaxDistance:3D音频最大距离]}</param>
|
||||||
public static void PlaySFX(AudioData audioData)
|
public static void PlaySFX(AudioData audioData)
|
||||||
{
|
{
|
||||||
if(SFX == null) Initialize();
|
if (SFX == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("AudioCoreManager: SFX is null, please initialize it first.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
SFX.Play(audioData);
|
SFX.Play(audioData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +100,11 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static void StopAllSFX()
|
public static void StopAllSFX()
|
||||||
{
|
{
|
||||||
if(SFX == null) return;
|
if (SFX == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("AudioCoreManager: SFX is null, please initialize it first.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
AudioData audioData = new AudioData();
|
AudioData audioData = new AudioData();
|
||||||
SFX.Stop();
|
SFX.Stop();
|
||||||
}
|
}
|
||||||
@@ -99,18 +121,28 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// [audio3DMaxDistance:3D音频最大距离]}</param>
|
/// [audio3DMaxDistance:3D音频最大距离]}</param>
|
||||||
public static void PlayMusic(AudioData audioData)
|
public static void PlayMusic(AudioData audioData)
|
||||||
{
|
{
|
||||||
if(Music == null) Initialize();
|
if (Music == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("AudioCoreManager: Music is null, please initialize it first.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
Music.Play(audioData);
|
Music.Play(audioData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置背景音乐音量
|
/// Bgm设置自然过渡到指定音量
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="audioData">{[volume:音量], [fadeDuration:自然过渡时间]}</param>
|
/// <param name="fadeDuration"></param>
|
||||||
public static void SetMusicVolume(AudioData audioData)
|
/// <param name="targetVolume"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static void SetMusicVolume(float fadeDuration, float targetVolume)
|
||||||
{
|
{
|
||||||
if(Music == null) return;
|
if (Music == null)
|
||||||
Music.SetMusicVolume(audioData);
|
{
|
||||||
|
Debug.LogError("AudioCoreManager: Music is null, please initialize it first.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Music.SetMusicVolume(fadeDuration, targetVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -120,10 +152,12 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// <param name="fadeDuration">自然过渡时间</param>
|
/// <param name="fadeDuration">自然过渡时间</param>
|
||||||
public static void StopMusic(float fadeDuration = 1f)
|
public static void StopMusic(float fadeDuration = 1f)
|
||||||
{
|
{
|
||||||
if(Music == null) return;
|
if (Music == null)
|
||||||
AudioData audioData = new AudioData();
|
{
|
||||||
audioData.fadeDuration = fadeDuration;
|
Debug.LogError("AudioCoreManager: Music is null, please initialize it first.");
|
||||||
Music.Stop(audioData);
|
return;
|
||||||
|
}
|
||||||
|
Music.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -132,14 +166,14 @@ namespace Stary.Evo.AudioCore
|
|||||||
/// 重新初始化
|
/// 重新初始化
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static void Reinitialize()
|
public static void Dispose()
|
||||||
{
|
{
|
||||||
if (audioSourcePool == null) Initialize();
|
|
||||||
|
|
||||||
StopVoice();
|
StopVoice();
|
||||||
StopAllSFX();
|
StopAllSFX();
|
||||||
StopMusic();
|
StopMusic();
|
||||||
|
Voice = null;
|
||||||
|
SFX = null;
|
||||||
|
Music = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "com.audiocore.runtime",
|
"name": "com.audiocore.runtime",
|
||||||
"rootNamespace": "",
|
"rootNamespace": "",
|
||||||
"references": [],
|
"references": [
|
||||||
|
"GUID:f51ebe6a0ceec4240a699833d6309b23"
|
||||||
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
"allowUnsafeCode": false,
|
"allowUnsafeCode": false,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "com.staryevo.audiocore",
|
"name": "com.staryevo.audiocore",
|
||||||
"version": "1.0.20",
|
"version": "1.1.0",
|
||||||
"displayName": "04.AudioCore",
|
"displayName": "04.AudioCore",
|
||||||
"description": "音频播放工具",
|
"description": "音频播放工具",
|
||||||
"unity": "2021.3",
|
"unity": "2021.3",
|
||||||
@@ -9,6 +9,9 @@
|
|||||||
"unity",
|
"unity",
|
||||||
"scirpt"
|
"scirpt"
|
||||||
],
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"com.cysharp.unitask": "2.5.10"
|
||||||
|
},
|
||||||
"author": {
|
"author": {
|
||||||
"name": "staryEvo",
|
"name": "staryEvo",
|
||||||
"url": "https://www.unity3d.com"
|
"url": "https://www.unity3d.com"
|
||||||
|
|||||||
Reference in New Issue
Block a user