音效模块
音效系統
1.個人思路
1.情景假設
一天,小明想聽歌。于是,他拿起手機,找到音樂播放軟件,選擇歌曲,按下播放鍵,聽到了想聽的歌
2.過程分析
1 小明想聽歌 -> 聽歌的對象,歌曲信息接收者
2 打開音樂播放軟件 -> 播放音樂的對象,音效源
3 選擇歌曲 -> 選擇的數據,音效資源3.實現思路
AudioListener: 音效的監聽者
AudioSources:音頻控制器
AudioClip:音頻文件
2.代碼實現
2.1 簡易播放器
`using UnityEngine;// 添加音效源 [RequireComponent(typeof(AudioSource))] public class AudioManagerA : MonoBehaviour{public AudioClip AudioClip;private AudioSource _audioSource;private void Start(){_audioSource = GetComponent<AudioSource>();}// 播放音效public void PlayAudio(float volume = 1.0f, bool isLoop = false){_audioSource.clip = AudioClip;_audioSource.volume = volume;_audioSource.loop = isLoop;_audioSource.Play();Debug.LogFormat("播放音效: {0}", AudioClip.name);} }``using UnityEngine;public class TestA : MonoBehaviour {public bool IsPlayAudio;void Start () {gameObject.AddComponent<AudioManagerA>();// 選擇播放的音效gameObject.GetComponent<AudioManagerA>().AudioClip = Resources.Load<AudioClip>("Audio/BackgroundMusic/BgMusic"); }void Update () {if (IsPlayAudio){IsPlayAudio = false;gameObject.GetComponent<AudioManagerA>().PlayAudio();} } }`2.2 如何方便的選擇音效文件
` using System; using System.Collections.Generic; using UnityEngine;public interface IUploadAudio {// 加載音效資源AudioClip GetAudioClip(string audioName); }[RequireComponent(typeof(AudioSource))] public class AudioManagerB : MonoBehaviour, IUploadAudio {// 保存已經加載過的音效 private Dictionary<string, AudioClip> _audioDict; private AudioSource _audioSource;private void Start() {_audioDict = new Dictionary<string, AudioClip>();_audioSource = GetComponent<AudioSource>(); }// 播放音效 public void PlayAudio(string audioName, float volume = 1.0f, bool isLoop = false) {if (!_audioDict.ContainsKey(audioName)){_audioDict.Add(audioName, GetAudioClip(audioName));}_audioSource.clip = _audioDict[audioName];_audioSource.volume = volume;_audioSource.loop = isLoop;_audioSource.Play(); }public AudioClip GetAudioClip(string audioName) {AudioClip audioClip = Resources.Load<AudioClip>(audioName);if (audioClip == null){throw new Exception("沒有找到相應的音效資源 請確認路徑:" + audioName);}return audioClip; } }``using UnityEngine;public class TestB : MonoBehaviour {public bool IsPlayAudio; public string AudioName;void Start() {AudioName = "Audio/BackgroundMusic/BgMusic";gameObject.AddComponent<AudioManagerB>(); }void Update() {if (IsPlayAudio){IsPlayAudio = false;gameObject.GetComponent<AudioManagerB>().PlayAudio(AudioName);} } }`
2.2.1 使用一個音效路徑管理類
`public class AudioPath {public const string BACKGROUND_MUSIC = "Audio/BackgroundMusic/BgMusic";public const string BACKGROUND_MUSIC_B = "Audio/BackgroundMusic/BgMusicB";public const string BACKGROUND_MUSIC_C = "Audio/BackgroundMusic/BgMusicC";public const string BACKGROUND_MUSIC_D = "Audio/BackgroundMusic/BgMusicD";}`2.2.2 使用枚舉組裝路徑
`public class AudioType {public enum Dialogue {}public enum ScreenOnClick {// 點擊正確Correct,// 點擊錯誤Error, }public enum SpecialEffects {}public enum BackgroundMusic {// 背景音樂BgMusic, }public enum Other {} }``using UnityEngine;public class TestB : MonoBehaviour {public bool IsPlayAudio;void Start() {gameObject.AddComponent<AudioManagerB>(); }void Update() {if (IsPlayAudio){IsPlayAudio = false;gameObject.GetComponent<AudioManagerB>().PlayAudio(AudioType.BackgroundMusic.BgMusic);} } }`
`using System; using System.Collections.Generic; using UnityEngine;public interface IUploadAudio { // 加載音效資源 AudioClip GetAudioClip(Enum audioName); }[RequireComponent(typeof(AudioSource))] public class AudioManagerB : MonoBehaviour, IUploadAudio {// 保存已經加載過的音效 private Dictionary<Enum, AudioClip> _audioDict; private AudioSource _audioSource; private const string audioPath = "Audio/";private void Start() {_audioDict = new Dictionary<Enum, AudioClip>();_audioSource = GetComponent<AudioSource>(); }// 播放音效 public void PlayAudio(Enum audioName, float volume = 1.0f, bool isLoop = false) {if (!_audioDict.ContainsKey(audioName)){_audioDict.Add(audioName, GetAudioClip(audioName));}_audioSource.clip = _audioDict[audioName];_audioSource.volume = volume;_audioSource.loop = isLoop;_audioSource.Play(); }public AudioClip GetAudioClip(Enum audioName) {string audioType = audioName.GetType().Name;AudioClip audioClip = Resources.Load<AudioClip>(audioPath + audioType + "/" + audioName);if (audioClip == null){throw new Exception("沒有找到相應的音效資源 請確認路徑:" + audioName);}return audioClip; } }`
2.3 考慮多個播放源
2.3.1 接口設置
`public interface IUploadAudioClip { // 加載音效資源 AudioClip GetAudioClip(Enum audioName); }public interface IUploadAudioSource { // 加載音效播放源 AudioSource GetAudioSource(string audioSourceName); }public interface IPlayAudio { // 播放音效 void PlayAudio(Enum audioName, float volume, bool isLoop, string audioSourceName); // 停止播放的音效 void StopAudio(string audioSourceName); }`2.3.2 播放源系統
` public class UploadAudioSourceStrategy : IUploadAudioSource { // 播放的音頻源 private Dictionary<string, AudioSource> audioSourceDict; // 音效管理器 private GameObject audioControl; private static int count; private readonly string currentAudioName;public UploadAudioSourceStrategy() {audioSourceDict = new Dictionary<string, AudioSource>(3);audioControl = new GameObject { name = "AudioModuleControl" };Object.DontDestroyOnLoad(audioControl);audioControl.AddComponent<AudioListener>(); }public AudioSource GetAudioSource(string audioSourceName) {if(audioSourceName.Equals(string.Empty)){return GetCurrentAudioSource();}if (audioSourceDict.ContainsKey(audioSourceName)){return audioSourceDict[audioSourceName];}return GetCurrentAudioSource(audioSourceName); }private AudioSource GetCurrentAudioSource() {foreach (var source in audioSourceDict){if (!source.Value.isPlaying){return source.Value;}}return GetCurrentAudioSource(currentAudioName + count++); }private AudioSource GetCurrentAudioSource(string audioSourceName) {audioSourceDict.Add(audioSourceName, audioControl.AddComponent<AudioSource>());return audioSourceDict[audioSourceName]; } }`2.3.3 音效資源系統
`public class UploadAudioClipStrategy : IUploadAudioClip {// 音效路徑 private readonly string audioPath; // 播放的音效 private Dictionary<Enum, AudioClip> audioClipDict;public UploadAudioClipStrategy() {audioPath = "Audio/";audioClipDict = new Dictionary<Enum, AudioClip>(); }public AudioClip GetAudioClip(Enum audioName) {if (audioClipDict.ContainsKey(audioName)){return audioClipDict[audioName];}AudioClip clip = Resources.Load<AudioClip>(AudioClipPath(audioName));audioClipDict.Add(audioName, clip);return audioClipDict[audioName]; }private string AudioClipPath(Enum audioName) {string audioType = audioName.GetType().Name;return audioPath + audioType + "/" + audioName; } }`
2.3.4 音效系統
` public abstract class AudioManagerBase : IPlayAudio { public IUploadAudioSource UploadAudioSource { get; protected set; } public IUploadAudioClip UploadAudioClip { get; protected set; }protected AudioManagerBase() : this(new UploadAudioSourceStrategy(), new UploadAudioClipStrategy()) {}protected AudioManagerBase(IUploadAudioSource uploadAudioSource, IUploadAudioClip uploadAudioClip) {UploadAudioSource = uploadAudioSource;UploadAudioClip = uploadAudioClip; }public void PlayAudio(Enum audioName, float volume, bool isLoop, string audioSourceName) {AudioClip clip = UploadAudioClip.GetAudioClip(audioName);AudioSource audioSource = UploadAudioSource.GetAudioSource(audioSourceName);audioSource.clip = clip;audioSource.volume = volume;audioSource.loop = isLoop;audioSource.Play(); }public void StopAudio(string audioSourceName) {AudioSource audioSource = UploadAudioSource.GetAudioSource(audioSourceName);audioSource.loop = false;audioSource.Stop(); } }`` public class AudioSourceManager : AudioManagerBase {public const string BgAudioName = "BgAudio";#region 播放音樂的調用方式 public void PlayAudio(AudioType.Dialogue audioName, float volume = 1.0f, bool isLoop = false, string audioSourceName = "") {base.PlayAudio(audioName, volume, isLoop, audioSourceName); }public void PlayAudio(AudioType.ScreenOnClick audioName, float volume = 1.0f, bool isLoop = false, string audioSourceName = "") {base.PlayAudio(audioName, volume, isLoop, audioSourceName); }public void PlayAudio(AudioType.SpecialEffects audioName, float volume = 1.0f, bool isLoop = false, string audioSourceName = "") {base.PlayAudio(audioName, volume, isLoop, audioSourceName); }public void PlayAudio(AudioType.Other audioName, float volume = 1.0f, bool isLoop = false, string audioSourceName = "") {base.PlayAudio(audioName, volume, isLoop, audioSourceName); }public void PlayAudio(AudioType.BackgroundMusic audioName, string audioSourceName = BgAudioName, float volume = 1.0f, bool isLoop = true) {PlayAudio(audioName, volume, isLoop, audioSourceName); }#endregion}
`
2.3.5 播放測試
`using UnityEngine;public class TestC : MonoBehaviour {private void Start() {AudioSourceManager audioSourceManager = new AudioSourceManager();audioSourceManager.PlayAudio(AudioType.BackgroundMusic.BgMusic);audioSourceManager.PlayAudio(AudioType.ScreenOnClick.Correct);audioSourceManager.PlayAudio(AudioType.ScreenOnClick.Error); } }`2.4 常用方法擴展
`public interface IUploadAudioSource {。。。 // 停止選擇的部分音效 void StopGroupAudio(Func<string, bool> stopGroupAudio); }``public class UploadAudioSourceStrategy : IUploadAudioSource{。。。public void StopGroupAudio(Func<string, bool> stopGroupAudio){foreach (var source in audioSourceDict){if (stopGroupAudio(source.Key)){source.Value.loop = false;source.Value.Stop();}}} }``public abstract class AudioManagerBase : IPlayAudio{。。。public void Reset(Func<string, bool> stopGroupAudio){UploadAudioSource.StopGroupAudio(stopGroupAudio);}public float PlayAudioTime(Enum audioName){if (UploadAudioClip.GetAudioClip(audioName) == null){Debug.Log("Error: " + "The music file could not be found");return 0.0f;}return UploadAudioClip.GetAudioClip(audioName).length;} }``public class AudioSourceManager : AudioManagerBase, ISingleton {。。。private AudioSourceManager() { }public const string BgAudioName = "BgAudio"; }``public class TestC : MonoBehaviour {private void Start(){SingletonManager.GetSingleton<AudioSourceManager>().PlayAudio(AudioType.BackgroundMusic.BgMusic);SingletonManager.GetSingleton<AudioSourceManager>().PlayAudio(AudioType.ScreenOnClick.Correct);SingletonManager.GetSingleton<AudioSourceManager>().PlayAudio(AudioType.ScreenOnClick.Error);} }`轉載于:https://www.cnblogs.com/programmingAdorableNew/p/10344811.html
總結
- 上一篇: 绝地求生画面设置2018
- 下一篇: slaaloo是什么型号