mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-07 16:45:10 +00:00
Commit AudioMixer
Commit AudioMixer
This commit is contained in:
3
Assets/TEngine/Runtime/GameFramework/Audio.meta
Normal file
3
Assets/TEngine/Runtime/GameFramework/Audio.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d87223177a947e0b00099b362582d6f
|
||||
timeCreated: 1680687445
|
132
Assets/TEngine/Runtime/GameFramework/Audio/AudioCategory.cs
Normal file
132
Assets/TEngine/Runtime/GameFramework/Audio/AudioCategory.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Audio;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class AudioCategory
|
||||
{
|
||||
public List<AudioData> _audioObjects;
|
||||
AudioMixerGroup _audioMixerGroup;
|
||||
int _maxChannel;
|
||||
bool _bEnable = true;
|
||||
|
||||
public bool Enable
|
||||
{
|
||||
get => _bEnable;
|
||||
set
|
||||
{
|
||||
if (_bEnable != value)
|
||||
{
|
||||
_bEnable = value;
|
||||
if (!_bEnable)
|
||||
{
|
||||
for (int i = 0; i < _audioObjects.Count; ++i)
|
||||
{
|
||||
if (_audioObjects[i] != null)
|
||||
{
|
||||
_audioObjects[i].Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public AudioCategory(int maxChannel, AudioMixerGroup audioMixerGroup)
|
||||
{
|
||||
_maxChannel = maxChannel;
|
||||
_audioObjects = new List<AudioData>();
|
||||
for (int i = 0; i < _maxChannel; i++)
|
||||
{
|
||||
AudioData audioData = new AudioData();
|
||||
audioData.Init(audioMixerGroup);
|
||||
_audioObjects.Add(audioData);
|
||||
}
|
||||
|
||||
_audioMixerGroup = audioMixerGroup;
|
||||
}
|
||||
|
||||
public void AddAudio(int num)
|
||||
{
|
||||
_maxChannel += num;
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
_audioObjects.Add(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public AudioData Play(string path, bool bAsync, bool bInPool = false)
|
||||
{
|
||||
if (!_bEnable)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int freeChannel = -1;
|
||||
float duration = -1;
|
||||
int num = 0;
|
||||
for (int i = 0; i < _audioObjects.Count; ++i)
|
||||
{
|
||||
if (_audioObjects[i] != null && _audioObjects[i]._assetData != null && _audioObjects[i].IsFinish == false)
|
||||
{
|
||||
if (path.Equals(_audioObjects[i]._assetData.Path))
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _audioObjects.Count; i++)
|
||||
{
|
||||
if (_audioObjects[i]._assetData == null || _audioObjects[i].IsFinish == true)
|
||||
{
|
||||
freeChannel = i;
|
||||
break;
|
||||
}
|
||||
else if (_audioObjects[i].Duration > duration)
|
||||
{
|
||||
duration = _audioObjects[i].Duration;
|
||||
freeChannel = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (freeChannel >= 0)
|
||||
{
|
||||
if (_audioObjects[freeChannel] == null)
|
||||
_audioObjects[freeChannel] = AudioData.Create(path, bAsync, _audioMixerGroup, bInPool);
|
||||
else
|
||||
_audioObjects[freeChannel].Load(path, bAsync, bInPool);
|
||||
return _audioObjects[freeChannel];
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"Here is no channel to play audio {path}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop(bool fadeout)
|
||||
{
|
||||
for (int i = 0; i < _audioObjects.Count; ++i)
|
||||
{
|
||||
if (_audioObjects[i] != null)
|
||||
{
|
||||
_audioObjects[i].Stop(fadeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(float delta)
|
||||
{
|
||||
for (int i = 0; i < _audioObjects.Count; ++i)
|
||||
{
|
||||
if (_audioObjects[i] != null)
|
||||
{
|
||||
_audioObjects[i].Update(delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5921a62f1450440db2f5141978a7394c
|
||||
timeCreated: 1680687799
|
293
Assets/TEngine/Runtime/GameFramework/Audio/AudioData.cs
Normal file
293
Assets/TEngine/Runtime/GameFramework/Audio/AudioData.cs
Normal file
@@ -0,0 +1,293 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Audio;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class AudioData
|
||||
{
|
||||
int _id = 0;
|
||||
public AssetData _assetData = null;
|
||||
public AudioSource _source = null;
|
||||
Transform _transform = null;
|
||||
float _volume = 1.0f;
|
||||
float _duration = 0;
|
||||
float _fadeoutTimer = 0f;
|
||||
const float FadeoutDuration = 0.2f;
|
||||
private bool _inPool = false;
|
||||
|
||||
enum State
|
||||
{
|
||||
None,
|
||||
Loading,
|
||||
Playing,
|
||||
FadingOut,
|
||||
End,
|
||||
};
|
||||
|
||||
State _state = State.None;
|
||||
|
||||
class LoadRequest
|
||||
{
|
||||
public string path;
|
||||
public bool bAsync;
|
||||
}
|
||||
|
||||
LoadRequest _pendingLoad = null;
|
||||
|
||||
public int ID
|
||||
{
|
||||
get { return _id; }
|
||||
}
|
||||
|
||||
public float Volume
|
||||
{
|
||||
set
|
||||
{
|
||||
if (_source != null)
|
||||
{
|
||||
_volume = value;
|
||||
_source.volume = _volume;
|
||||
}
|
||||
}
|
||||
get { return _volume; }
|
||||
}
|
||||
|
||||
public bool IsFinish
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_source != null)
|
||||
return _state == State.End;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public float Duration
|
||||
{
|
||||
get { return _duration; }
|
||||
}
|
||||
|
||||
public float Length
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_source != null && _source.clip != null)
|
||||
{
|
||||
return _source.clip.length;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 Position
|
||||
{
|
||||
get { return _transform.position; }
|
||||
set { _transform.position = value; }
|
||||
}
|
||||
|
||||
public bool IsLoop
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_source != null)
|
||||
return _source.loop;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_source != null)
|
||||
_source.loop = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsPlaying
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_source != null && _source.isPlaying)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AudioSource AudioResource()
|
||||
{
|
||||
return _source;
|
||||
}
|
||||
|
||||
public static AudioData Create(string path, bool bAsync, AudioMixerGroup audioMixerGroup, bool bInPool = false)
|
||||
{
|
||||
AudioData audioData = new AudioData();
|
||||
audioData.Init(audioMixerGroup);
|
||||
audioData.Load(path, bAsync, bInPool);
|
||||
|
||||
return audioData;
|
||||
}
|
||||
|
||||
public void Init(AudioMixerGroup audioMixerGroup)
|
||||
{
|
||||
GameObject host = new GameObject("Audio");
|
||||
host.transform.SetParent(AudioManager.Instance.transform);
|
||||
host.transform.localPosition = Vector3.zero;
|
||||
_transform = host.transform;
|
||||
_source = host.AddComponent<AudioSource>();
|
||||
_source.playOnAwake = false;
|
||||
_source.outputAudioMixerGroup = audioMixerGroup;
|
||||
_id = _source.GetInstanceID();
|
||||
}
|
||||
|
||||
public void Load(string path, bool bAsync, bool bInPool = false)
|
||||
{
|
||||
_inPool = bInPool;
|
||||
if (_state == State.None || _state == State.End)
|
||||
{
|
||||
_duration = 0;
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
if (AudioManager.Instance._audioClipPool.ContainsKey(path))
|
||||
{
|
||||
OnAssetLoadComplete(AudioManager.Instance._audioClipPool[path]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bAsync)
|
||||
{
|
||||
_state = State.Loading;
|
||||
AssetManager.Instance.GetAssetAsync(path, false, OnAssetLoadComplete);
|
||||
}
|
||||
else
|
||||
OnAssetLoadComplete(AssetManager.Instance.GetAsset(path, false));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_pendingLoad = new LoadRequest { path = path, bAsync = bAsync };
|
||||
|
||||
if (_state == State.Playing)
|
||||
{
|
||||
Stop(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop(bool fadeout = false)
|
||||
{
|
||||
if (_source != null)
|
||||
{
|
||||
if (fadeout)
|
||||
{
|
||||
_fadeoutTimer = FadeoutDuration;
|
||||
_state = State.FadingOut;
|
||||
}
|
||||
else
|
||||
{
|
||||
_source.Stop();
|
||||
_state = State.End;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnAssetLoadComplete(AssetData assetData)
|
||||
{
|
||||
if (assetData != null)
|
||||
{
|
||||
assetData.OnAsyncLoadComplete -= OnAssetLoadComplete;
|
||||
if (_inPool && !AudioManager.Instance._audioClipPool.ContainsKey(assetData.Path))
|
||||
{
|
||||
assetData.AddRef();
|
||||
AudioManager.Instance._audioClipPool.Add(assetData.Path, assetData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_pendingLoad != null)
|
||||
{
|
||||
assetData.AddRef();
|
||||
if (assetData != null)
|
||||
assetData.DecRef();
|
||||
_state = State.End;
|
||||
string path = _pendingLoad.path;
|
||||
bool bAsync = _pendingLoad.bAsync;
|
||||
_pendingLoad = null;
|
||||
Load(path, bAsync);
|
||||
}
|
||||
else if (assetData != null)
|
||||
{
|
||||
assetData.AddRef();
|
||||
if (_assetData != null)
|
||||
{
|
||||
_assetData.DecRef();
|
||||
}
|
||||
_assetData = assetData;
|
||||
|
||||
_source.clip = _assetData.AssetObject as AudioClip;
|
||||
if (_source.clip != null)
|
||||
{
|
||||
_source.Play();
|
||||
_state = State.Playing;
|
||||
}
|
||||
else
|
||||
{
|
||||
_state = State.End;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_state = State.End;
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(float delta)
|
||||
{
|
||||
if (_state == State.Playing)
|
||||
{
|
||||
if (!_source.isPlaying)
|
||||
_state = State.End;
|
||||
}
|
||||
else if (_state == State.FadingOut)
|
||||
{
|
||||
if (_fadeoutTimer > 0f)
|
||||
{
|
||||
_fadeoutTimer -= delta;
|
||||
_source.volume = _volume * _fadeoutTimer / FadeoutDuration;
|
||||
}
|
||||
else
|
||||
{
|
||||
Stop();
|
||||
if (_pendingLoad != null)
|
||||
{
|
||||
string path = _pendingLoad.path;
|
||||
bool bAsync = _pendingLoad.bAsync;
|
||||
_pendingLoad = null;
|
||||
Load(path, bAsync);
|
||||
}
|
||||
|
||||
_source.volume = _volume;
|
||||
}
|
||||
}
|
||||
|
||||
_duration += delta;
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
if (_transform != null)
|
||||
{
|
||||
Object.Destroy(_transform.gameObject);
|
||||
}
|
||||
|
||||
if (_assetData != null)
|
||||
{
|
||||
_assetData.DecRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64948e44dfc74661bbde806c89084cf5
|
||||
timeCreated: 1680687659
|
428
Assets/TEngine/Runtime/GameFramework/Audio/AudioModule.cs
Normal file
428
Assets/TEngine/Runtime/GameFramework/Audio/AudioModule.cs
Normal file
@@ -0,0 +1,428 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Audio;
|
||||
using UnityEngine.Networking;
|
||||
using YooAsset;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class ChannelNumConfig
|
||||
{
|
||||
public int MaxChannelNum;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 音效管理,为游戏提供统一的音效播放接口。
|
||||
/// </summary>
|
||||
/// <remarks>场景3D音效挂到场景物件、技能3D音效挂到技能特效上,并在AudioSource的Output上设置对应分类的AudioMixerGroup</remarks>
|
||||
public class AudioManager : GameFrameworkModuleBase
|
||||
{
|
||||
private AudioMixer _audioMixer;
|
||||
private float _volume = 1f;
|
||||
private bool _enable = true;
|
||||
public Dictionary<string, int> _soundConfigDic = new Dictionary<string, int>();
|
||||
private int _audioChannelMaxNum = 0;
|
||||
AudioCategory[] _audioCategories = new AudioCategory[(int)AudioType.Max];
|
||||
float[] _categoriesVolume = new float[(int)AudioType.Max];
|
||||
public Dictionary<string, AssetOperationHandle> _audioClipPool = new Dictionary<string, AssetOperationHandle>();
|
||||
|
||||
private bool _bUnityAudioDisabled = false;
|
||||
|
||||
/// <summary>
|
||||
/// 总音量控制
|
||||
/// </summary>
|
||||
public float Volume
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return 0.0f;
|
||||
return _volume;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return;
|
||||
_volume = value;
|
||||
AudioListener.volume = _volume;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 总开关
|
||||
/// </summary>
|
||||
public bool Enable
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return false;
|
||||
return _enable;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return;
|
||||
_enable = value;
|
||||
AudioListener.volume = _enable ? _volume : 0f;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 音乐音量
|
||||
/// </summary>
|
||||
public float MusicVolume
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return 0.0f;
|
||||
return _categoriesVolume[(int)AudioType.Music];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return;
|
||||
float volume = Mathf.Clamp(value, 0.0001f, 1.0f);
|
||||
_categoriesVolume[(int)AudioType.Music] = volume;
|
||||
|
||||
_audioMixer.SetFloat("MusicVolume", Mathf.Log10(volume) * 20f);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 音效音量
|
||||
/// </summary>
|
||||
public float SoundVolume
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return 0.0f;
|
||||
return _categoriesVolume[(int)AudioType.Sound];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return;
|
||||
float volume = Mathf.Clamp(value, 0.0001f, 1.0f);
|
||||
_categoriesVolume[(int)AudioType.Sound] = volume;
|
||||
_audioMixer.SetFloat("SoundVolume", Mathf.Log10(volume) * 20f);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 语音音量
|
||||
/// </summary>
|
||||
public float VoiceVolume
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return 0.0f;
|
||||
return _categoriesVolume[(int)AudioType.Voice];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return;
|
||||
float volume = Mathf.Clamp(value, 0.0001f, 1.0f);
|
||||
_categoriesVolume[(int)AudioType.Voice] = volume;
|
||||
_audioMixer.SetFloat("VoiceVolume", Mathf.Log10(volume) * 20f);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 音乐开关
|
||||
/// </summary>
|
||||
public bool MusicEnable
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return false;
|
||||
float db;
|
||||
if (_audioMixer.GetFloat("MusicVolume", out db))
|
||||
return db > -80f;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return;
|
||||
// 音乐采用0音量方式,避免恢复播放时的复杂逻辑
|
||||
if (value)
|
||||
_audioMixer.SetFloat("MusicVolume", Mathf.Log10(_categoriesVolume[(int)AudioType.Music]) * 20f);
|
||||
else
|
||||
_audioMixer.SetFloat("MusicVolume", -80f);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 音效开关
|
||||
/// </summary>
|
||||
public bool SoundEnable
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return false;
|
||||
return _audioCategories[(int)AudioType.Sound].Enable;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return;
|
||||
_audioCategories[(int)AudioType.Sound].Enable = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 语音开关
|
||||
/// </summary>
|
||||
public bool VoiceEnable
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return false;
|
||||
return _audioCategories[(int)AudioType.Voice].Enable;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
return;
|
||||
_audioCategories[(int)AudioType.Voice].Enable = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal AudioMixer audioMixer
|
||||
{
|
||||
get { return _audioMixer; }
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
try
|
||||
{
|
||||
TypeInfo typeInfo = typeof(AudioSettings).GetTypeInfo();
|
||||
PropertyInfo propertyInfo = typeInfo.GetDeclaredProperty("unityAudioDisabled");
|
||||
_bUnityAudioDisabled = (bool)propertyInfo.GetValue(null);
|
||||
if (_bUnityAudioDisabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e.ToString());
|
||||
}
|
||||
|
||||
_audioMixer = Resources.Load<AudioMixer>("AudioMixer");
|
||||
|
||||
for (int i = 0; i < (int)AudioType.Max; ++i)
|
||||
{
|
||||
int channelMaxNum = 0;
|
||||
if (i == (int)AudioType.Sound)
|
||||
{
|
||||
channelMaxNum = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
channelMaxNum = 1;
|
||||
}
|
||||
_audioCategories[i] = new AudioCategory(channelMaxNum, audioMixer.FindMatchingGroups(((AudioType)i).ToString())[0]);
|
||||
_categoriesVolume[i] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public void Restart()
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
CleanSoundPool();
|
||||
for (int i = 0; i < (int)AudioType.Max; ++i)
|
||||
{
|
||||
if (_audioCategories[i] != null)
|
||||
{
|
||||
for (int j = 0; j < _audioCategories[i]._audioObjects.Count; ++j)
|
||||
{
|
||||
if (_audioCategories[i]._audioObjects[j] != null)
|
||||
{
|
||||
_audioCategories[i]._audioObjects[j].Destroy();
|
||||
_audioCategories[i]._audioObjects[j] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_audioCategories[i] = null;
|
||||
}
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 播放,如果超过最大发声数采用fadeout的方式复用最久播放的AudioSource
|
||||
/// </summary>
|
||||
/// <param name="type">声音类型</param>
|
||||
/// <param name="path">声音文件路径,通过右键菜单Get Asset Path获取的路径</param>
|
||||
/// <param name="bLoop">是否循环播放</param>>
|
||||
/// <param name="volume">音量(0-1.0)</param>
|
||||
/// <param name="bAsync">是否异步加载</param>
|
||||
public AudioData Play(AudioType type, string path, bool bLoop = false, float volume = 1.0f, bool bAsync = false, bool bInPool = false)
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AudioData audioData = _audioCategories[(int)type].Play(path, bAsync, bInPool);
|
||||
{
|
||||
if (audioData != null)
|
||||
{
|
||||
audioData.IsLoop = bLoop;
|
||||
audioData.Volume = volume;
|
||||
}
|
||||
|
||||
return audioData;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止某类声音播放
|
||||
/// </summary>
|
||||
/// <param name="type">声音类型</param>
|
||||
/// <param name="fadeout">是否渐消</param>
|
||||
public void Stop(AudioType type, bool fadeout)
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_audioCategories[(int)type].Stop(fadeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止所有声音
|
||||
/// </summary>
|
||||
/// <param name="fadeout">是否渐消</param>
|
||||
public void StopAll(bool fadeout)
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < (int)AudioType.Max; ++i)
|
||||
{
|
||||
if (_audioCategories[i] != null)
|
||||
{
|
||||
_audioCategories[i].Stop(fadeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 修改最大的音效播放上限,
|
||||
/// </summary>
|
||||
/// <param name="num"></param> 最大播放数量
|
||||
public void ChangeAudioChannelMaxNum(int num)
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (num >= _audioChannelMaxNum)
|
||||
{
|
||||
_audioCategories[(int)AudioType.Sound].AddAudio(num - _audioChannelMaxNum);
|
||||
_audioChannelMaxNum = num;
|
||||
}
|
||||
else
|
||||
{
|
||||
Stop(AudioType.Sound, true);
|
||||
_audioChannelMaxNum = num;
|
||||
_audioCategories[(int)AudioType.Sound].Enable = false;
|
||||
_audioCategories[(int)AudioType.Sound] = new AudioCategory(_audioChannelMaxNum, _audioMixer.FindMatchingGroups((AudioType.Sound).ToString())[0]);
|
||||
_categoriesVolume[(int)AudioType.Sound] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 预先加载AudioClip,并放入对象池
|
||||
/// </summary>
|
||||
/// <param name="list"></param>AudioClip的AssetPath集合
|
||||
public void PutInAudioPool(List<string> list)
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (string path in list)
|
||||
{
|
||||
if (_audioClipPool != null && !_audioClipPool.ContainsKey(path))
|
||||
{
|
||||
AssetOperationHandle assetData = AssetManager.Instance.GetAsset(path, false);
|
||||
_audioClipPool?.Add(assetData.Path, assetData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将部分AudioClip从对象池移出
|
||||
/// </summary>
|
||||
/// <param name="list"></param>AudioClip的AssetPath集合
|
||||
public void RemoveClipFromPool(List<string> list)
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (string path in list)
|
||||
{
|
||||
if (_audioClipPool.ContainsKey(path))
|
||||
{
|
||||
_audioClipPool[path].Dispose();
|
||||
_audioClipPool.Remove(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空AudioClip的对象池
|
||||
/// </summary>
|
||||
public void CleanSoundPool()
|
||||
{
|
||||
if (_bUnityAudioDisabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var dic in _audioClipPool)
|
||||
{
|
||||
dic.Value.Dispose();
|
||||
}
|
||||
|
||||
_audioClipPool.Clear();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
for (int i = 0; i < _audioCategories.Length; ++i)
|
||||
{
|
||||
if (_audioCategories[i] != null)
|
||||
{
|
||||
_audioCategories[i].Update(Time.deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13dea64094ab4501ba913acb560888fc
|
||||
timeCreated: 1680687658
|
26
Assets/TEngine/Runtime/GameFramework/Audio/AudioType.cs
Normal file
26
Assets/TEngine/Runtime/GameFramework/Audio/AudioType.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 音效分类,可分别关闭/开启对应分类音效。
|
||||
/// </summary>
|
||||
/// <remarks>命名与AudioMixer中分类名保持一致。</remarks>
|
||||
public enum AudioType
|
||||
{
|
||||
/// <summary>
|
||||
/// 声音
|
||||
/// </summary>
|
||||
Sound,
|
||||
/// <summary>
|
||||
/// 背景音乐
|
||||
/// </summary>
|
||||
Music,
|
||||
/// <summary>
|
||||
/// 人声
|
||||
/// </summary>
|
||||
Voice,
|
||||
/// <summary>
|
||||
/// 最大
|
||||
/// </summary>
|
||||
Max
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2da377437524fc6af7b2757cf36aab6
|
||||
timeCreated: 1680687690
|
21
Assets/TEngine/Runtime/GameFramework/Audio/Constant.cs
Normal file
21
Assets/TEngine/Runtime/GameFramework/Audio/Constant.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 声音相关常量。
|
||||
/// </summary>
|
||||
internal static class SoundConstant
|
||||
{
|
||||
internal const float DefaultTime = 0f;
|
||||
internal const bool DefaultMute = false;
|
||||
internal const bool DefaultLoop = false;
|
||||
internal const int DefaultPriority = 0;
|
||||
internal const float DefaultVolume = 1f;
|
||||
internal const float DefaultFadeInSeconds = 0f;
|
||||
internal const float DefaultFadeOutSeconds = 0f;
|
||||
internal const float DefaultPitch = 1f;
|
||||
internal const float DefaultPanStereo = 0f;
|
||||
internal const float DefaultSpatialBlend = 0f;
|
||||
internal const float DefaultMaxDistance = 100f;
|
||||
internal const float DefaultDopplerLevel = 1f;
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 165d290aafde4df4945ca30625396874
|
||||
timeCreated: 1680687464
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73905d9720c1293428e0db9c55b46d38
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,185 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!244 &-8165904320333843496
|
||||
AudioMixerEffectController:
|
||||
m_ObjectHideFlags: 3
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_EffectID: 6b8ac75d99b7e57489701e084ea19b1f
|
||||
m_EffectName: Attenuation
|
||||
m_MixLevel: b19e64315aff6dc4a81ae36b22fc0492
|
||||
m_Parameters: []
|
||||
m_SendTarget: {fileID: 0}
|
||||
m_EnableWetMix: 0
|
||||
m_Bypass: 0
|
||||
--- !u!243 &-4209890294574411305
|
||||
AudioMixerGroupController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Music
|
||||
m_AudioMixer: {fileID: 24100000}
|
||||
m_GroupID: efe8591c00084024187b9df78858c0af
|
||||
m_Children: []
|
||||
m_Volume: 6d4c2b8bc0ef38d44b2fbff2b3298ab4
|
||||
m_Pitch: 862389c428a73854ab442dd043008729
|
||||
m_Send: 00000000000000000000000000000000
|
||||
m_Effects:
|
||||
- {fileID: 246003612463095956}
|
||||
m_UserColorIndex: 0
|
||||
m_Mute: 0
|
||||
m_Solo: 0
|
||||
m_BypassEffects: 0
|
||||
--- !u!243 &-3395020342500439107
|
||||
AudioMixerGroupController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Voice
|
||||
m_AudioMixer: {fileID: 24100000}
|
||||
m_GroupID: 5117f9b5a365ec049a9d5891c563b893
|
||||
m_Children: []
|
||||
m_Volume: fe15a1b40c14ea646a13dacb15b6a73b
|
||||
m_Pitch: 3398197a464677a4186e0cecd66bb13c
|
||||
m_Send: 00000000000000000000000000000000
|
||||
m_Effects:
|
||||
- {fileID: -8165904320333843496}
|
||||
m_UserColorIndex: 0
|
||||
m_Mute: 0
|
||||
m_Solo: 0
|
||||
m_BypassEffects: 0
|
||||
--- !u!241 &24100000
|
||||
AudioMixerController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: AudioMixer
|
||||
m_OutputGroup: {fileID: 0}
|
||||
m_MasterGroup: {fileID: 24300002}
|
||||
m_Snapshots:
|
||||
- {fileID: 24500006}
|
||||
m_StartSnapshot: {fileID: 24500006}
|
||||
m_SuspendThreshold: -80
|
||||
m_EnableSuspend: 1
|
||||
m_UpdateMode: 0
|
||||
m_ExposedParameters:
|
||||
- guid: ba83e724007d7e9459f157db3a54a741
|
||||
name: MasterVolume
|
||||
- guid: 6d4c2b8bc0ef38d44b2fbff2b3298ab4
|
||||
name: MusicVolume
|
||||
- guid: 3bbd22597ed32714eb271cf06b098c63
|
||||
name: SoundVolume
|
||||
- guid: fe15a1b40c14ea646a13dacb15b6a73b
|
||||
name: VoiceVolume
|
||||
m_AudioMixerGroupViews:
|
||||
- guids:
|
||||
- 72c1e77b100e3274fbfb88ca2ca12c4d
|
||||
- efe8591c00084024187b9df78858c0af
|
||||
- 648e49a020cf83346a9220d606e4ff39
|
||||
- 5117f9b5a365ec049a9d5891c563b893
|
||||
name: View
|
||||
m_CurrentViewIndex: 0
|
||||
m_TargetSnapshot: {fileID: 24500006}
|
||||
--- !u!243 &24300002
|
||||
AudioMixerGroupController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Master
|
||||
m_AudioMixer: {fileID: 24100000}
|
||||
m_GroupID: 72c1e77b100e3274fbfb88ca2ca12c4d
|
||||
m_Children:
|
||||
- {fileID: -4209890294574411305}
|
||||
- {fileID: 7235523536312936115}
|
||||
- {fileID: -3395020342500439107}
|
||||
m_Volume: ba83e724007d7e9459f157db3a54a741
|
||||
m_Pitch: a2d2b77391464bb4887f0bcd3835015b
|
||||
m_Send: 00000000000000000000000000000000
|
||||
m_Effects:
|
||||
- {fileID: 24400004}
|
||||
m_UserColorIndex: 0
|
||||
m_Mute: 0
|
||||
m_Solo: 0
|
||||
m_BypassEffects: 0
|
||||
--- !u!244 &24400004
|
||||
AudioMixerEffectController:
|
||||
m_ObjectHideFlags: 3
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_EffectID: ce944d90cb57ee4418426132d391d900
|
||||
m_EffectName: Attenuation
|
||||
m_MixLevel: 891c3ec10e0ae1b42a95c83727d411f1
|
||||
m_Parameters: []
|
||||
m_SendTarget: {fileID: 0}
|
||||
m_EnableWetMix: 0
|
||||
m_Bypass: 0
|
||||
--- !u!245 &24500006
|
||||
AudioMixerSnapshotController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Snapshot
|
||||
m_AudioMixer: {fileID: 24100000}
|
||||
m_SnapshotID: 91dee90f8902c804c9da7728ea355157
|
||||
m_FloatValues:
|
||||
ba83e724007d7e9459f157db3a54a741: 0
|
||||
fe15a1b40c14ea646a13dacb15b6a73b: 0
|
||||
3bbd22597ed32714eb271cf06b098c63: 0
|
||||
6d4c2b8bc0ef38d44b2fbff2b3298ab4: 0
|
||||
m_TransitionOverrides: {}
|
||||
--- !u!244 &246003612463095956
|
||||
AudioMixerEffectController:
|
||||
m_ObjectHideFlags: 3
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_EffectID: 860c45ba06e3cbd4794061eaefe970a3
|
||||
m_EffectName: Attenuation
|
||||
m_MixLevel: bb4c221c9e3208941b1a2107831692ab
|
||||
m_Parameters: []
|
||||
m_SendTarget: {fileID: 0}
|
||||
m_EnableWetMix: 0
|
||||
m_Bypass: 0
|
||||
--- !u!244 &2567082640316932351
|
||||
AudioMixerEffectController:
|
||||
m_ObjectHideFlags: 3
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_EffectID: a7394d86e1e2a1e4389182f0aec98773
|
||||
m_EffectName: Attenuation
|
||||
m_MixLevel: cb8b6dfd682072d4fb81143ba077bc3f
|
||||
m_Parameters: []
|
||||
m_SendTarget: {fileID: 0}
|
||||
m_EnableWetMix: 0
|
||||
m_Bypass: 0
|
||||
--- !u!243 &7235523536312936115
|
||||
AudioMixerGroupController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Sound
|
||||
m_AudioMixer: {fileID: 24100000}
|
||||
m_GroupID: 648e49a020cf83346a9220d606e4ff39
|
||||
m_Children: []
|
||||
m_Volume: 3bbd22597ed32714eb271cf06b098c63
|
||||
m_Pitch: 7f8a6510dd472ff4db8b07c5079a2013
|
||||
m_Send: 00000000000000000000000000000000
|
||||
m_Effects:
|
||||
- {fileID: 2567082640316932351}
|
||||
m_UserColorIndex: 0
|
||||
m_Mute: 0
|
||||
m_Solo: 0
|
||||
m_BypassEffects: 0
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1af7a1b121ae17541a1967d430cef006
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user