在上一篇,我們完成了 GUIManager。
先列出 Manager Of Managers 如下:
(完成) MainManager: 作為入口管理器。
(已經有了) EventManager: 消息管理。
(完成) GUIManager: 圖形視圖管理。
AudioManager: 音效管理。
PoolManager: GameObject管理(減少動態開闢內存消耗,減少GC)。
LevelManager: 關卡管理。
GameManager: 遊戲管理。
SaveManager: 配置&存儲管理。
MenuManager 菜單管理。
下一個,我們要做的就是 AudioManager 了。
播放音頻功能AudioManager,字如其意就是音效管理。在 Unity 中我們需要用到的音效 API 有,AudioClip 、AudioSource、AudioListener。相信大家對它們已經很熟悉了。
我們還是以實際的問題去出發去完成這個 AudioManager。既然是音效管理,那麼它肯定要有音頻播放的功能。
我們呢就先馬上實現一個音頻播放的邏輯,先準備一個音效,放在我們的 Resources 目錄下,如下圖所示。
using UnityEngine;
namespace QFramework
{
public class AudioExample : MonoBehaviour
{
#if UNITY_EDITOR
[UnityEditor.MenuItem("QFramework/Example/13.AudioManager", false, 13)]
private static void MenuClicked()
{
UnityEditor.EditorApplication.isPlaying = true;
new GameObject("AudioExample")
.AddComponent<AudioExample>();
}
#endif
private void Start()
{
gameObject.AddComponent<AudioListener>();
var audioSource = gameObject.AddComponent<AudioSource>();
var coinSound = Resources.Load<AudioClip>("coin");
audioSource.clip = coinSound;
audioSource.Play();
}
}
}
執行之後,能聽到我們的音頻聲音,並且在場景中創建了一些東西,如下圖所示。
這樣一個音頻播放的功能就做完了。我們把以上的邏輯,整理成方法,放到我們的 AudioManager 腳本了。
代碼如下所示:
Assets/QFramework/Framework/Manager/AudioManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace QFramework
{
public class AudioManager : MonoBehaviour
{
public void PlaySound(string soundName)
{
gameObject.AddComponent<AudioListener>();
var audioSource = gameObject.AddComponent<AudioSource>();
var coinSound = Resources.Load<AudioClip>("coin");
audioSource.clip = coinSound;
audioSource.Play();
}
}
}
但是這樣寫了之後,我們的示例代碼就沒法訪問 PlaySound 這個方法了。所以呢,要把 AudioManager 做成一個單例。
代碼如下:
Assets/QFramework/Framework/Manager/AudioManager.cs
using UnityEngine;
namespace QFramework
{
public class AudioManager : MonoBehaviour
{
private static AudioManager mInstance;
public static AudioManager Instance
{
get
{
if (mInstance == null)
{
mInstance = new GameObject("AudioManager").AddComponent<AudioManager>();
DontDestroyOnLoad(mInstance);
}
return mInstance;
}
}
public void PlaySound(string soundName)
{
gameObject.AddComponent<AudioListener>();
var audioSource = gameObject.AddComponent<AudioSource>();
var coinSound = Resources.Load<AudioClip>("coin");
audioSource.clip = coinSound;
audioSource.Play();
}
}
}
單例的部分,我們用了一個 DontDestroyOnLoad 這樣的 API,它的意思是不管場景怎麼切換,這個 AudioManger 一直存在,不被銷毀。
這樣,我們的示例代碼就可以訪問 AudioManager 了。
示例代碼如下:
QFramework/Example/13.AudioManager/AudioExample.cs
using UnityEngine;
namespace QFramework
{
public class AudioExample : MonoBehaviour
{
#if UNITY_EDITOR
[UnityEditor.MenuItem("QFramework/Example/13.AudioManager", false, 13)]
private static void MenuClicked()
{
UnityEditor.EditorApplication.isPlaying = true;
new GameObject("AudioExample")
.AddComponent<AudioExample>();
}
#endif
private void Start()
{
AudioManager.Instance.PlaySound("coin");
}
}
}
運行之後,結果與原來的一致。
OK,第一個播放音頻功能就有了 ,雖然問題有很多……,但是有了……
完善播放功能現在我們的示例中只播放了一次音頻,但是我們要播放兩次呢?
示例代碼改成如下:
QFramework/Example/13.AudioManager/AudioExample.cs
using UnityEngine;
namespace QFramework
{
public class AudioExample : MonoBehaviour
{
#if UNITY_EDITOR
[UnityEditor.MenuItem("QFramework/Example/13.AudioManager", false, 13)]
private static void MenuClicked()
{
UnityEditor.EditorApplication.isPlaying = true;
new GameObject("AudioExample")
.AddComponent<AudioExample>();
}
#endif
private void Start()
{
AudioManager.Instance.PlaySound("coin");
AudioManager.Instance.PlaySound("coin");
}
}
}
運行之後結果如下:
我們先看看播放聲音的代碼
public void PlaySound(string soundName)
{
gameObject.AddComponent<AudioListener>();
var audioSource = gameObject.AddComponent<AudioSource>();
var coinSound = Resources.Load<AudioClip>(soundName);
audioSource.clip = coinSound;
audioSource.Play();
}
確實是,每次播放的時候,都會 AddComponet<AudioListener\>();
這部分解決起來比較簡單。
只要每次都判斷一次當前 GameObject 是否有 AudioListener 就好了。
代碼如下:
private AudioListener mAudioListener;
public void PlaySound(string soundName)
{
if (!mAudioListener)
{
mAudioListener = gameObject.AddComponent<AudioListener>();
}
var audioSource = gameObject.AddComponent<AudioSource>();
var coinSound = Resources.Load<AudioClip>(soundName);
audioSource.clip = coinSound;
audioSource.Play();
}
這樣就沒有邏輯上的問題了。
大家注意一下, audioListener 不是 bool 變量,但是它卻可以直接在 if 語句上當做表達式判斷。這是因為 Unity 對所有的 UnityEngine.Object 類型做了一個運算符重載。像我們的 MonoBehaviour、GameObject、Transform 全部都是可以這樣做的,因為它們都繼承了 UnityEngine.Object。
到這裡我們再運行一次示例。運行之後沒有任何問題。
不過這個問題不大。
今天的內容就這些,我們下一篇再見。
在上一篇,我們完成了 GUIManager。
先列出 Manager Of Managers 如下:
(完成) MainManager: 作為入口管理器。
(已經有了) EventManager: 消息管理。
(完成) GUIManager: 圖形視圖管理。
AudioManager: 音效管理。
PoolManager: GameObject管理(減少動態開闢內存消耗,減少GC)。
LevelManager: 關卡管理。
GameManager: 遊戲管理。
SaveManager: 配置&存儲管理。
MenuManager 菜單管理。
下一個,我們要做的就是 AudioManager 了。
播放音頻功能AudioManager,字如其意就是音效管理。在 Unity 中我們需要用到的音效 API 有,AudioClip 、AudioSource、AudioListener。相信大家對它們已經很熟悉了。
我們還是以實際的問題去出發去完成這個 AudioManager。既然是音效管理,那麼它肯定要有音頻播放的功能。
我們呢就先馬上實現一個音頻播放的邏輯,先準備一個音效,放在我們的 Resources 目錄下,如下圖所示。
using UnityEngine;
namespace QFramework
{
public class AudioExample : MonoBehaviour
{
#if UNITY_EDITOR
[UnityEditor.MenuItem("QFramework/Example/13.AudioManager", false, 13)]
private static void MenuClicked()
{
UnityEditor.EditorApplication.isPlaying = true;
new GameObject("AudioExample")
.AddComponent<AudioExample>();
}
#endif
private void Start()
{
gameObject.AddComponent<AudioListener>();
var audioSource = gameObject.AddComponent<AudioSource>();
var coinSound = Resources.Load<AudioClip>("coin");
audioSource.clip = coinSound;
audioSource.Play();
}
}
}
執行之後,能聽到我們的音頻聲音,並且在場景中創建了一些東西,如下圖所示。
這樣一個音頻播放的功能就做完了。我們把以上的邏輯,整理成方法,放到我們的 AudioManager 腳本了。
代碼如下所示:
Assets/QFramework/Framework/Manager/AudioManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace QFramework
{
public class AudioManager : MonoBehaviour
{
public void PlaySound(string soundName)
{
gameObject.AddComponent<AudioListener>();
var audioSource = gameObject.AddComponent<AudioSource>();
var coinSound = Resources.Load<AudioClip>("coin");
audioSource.clip = coinSound;
audioSource.Play();
}
}
}
但是這樣寫了之後,我們的示例代碼就沒法訪問 PlaySound 這個方法了。所以呢,要把 AudioManager 做成一個單例。
代碼如下:
Assets/QFramework/Framework/Manager/AudioManager.cs
using UnityEngine;
namespace QFramework
{
public class AudioManager : MonoBehaviour
{
private static AudioManager mInstance;
public static AudioManager Instance
{
get
{
if (mInstance == null)
{
mInstance = new GameObject("AudioManager").AddComponent<AudioManager>();
DontDestroyOnLoad(mInstance);
}
return mInstance;
}
}
public void PlaySound(string soundName)
{
gameObject.AddComponent<AudioListener>();
var audioSource = gameObject.AddComponent<AudioSource>();
var coinSound = Resources.Load<AudioClip>("coin");
audioSource.clip = coinSound;
audioSource.Play();
}
}
}
單例的部分,我們用了一個 DontDestroyOnLoad 這樣的 API,它的意思是不管場景怎麼切換,這個 AudioManger 一直存在,不被銷毀。
這樣,我們的示例代碼就可以訪問 AudioManager 了。
示例代碼如下:
QFramework/Example/13.AudioManager/AudioExample.cs
using UnityEngine;
namespace QFramework
{
public class AudioExample : MonoBehaviour
{
#if UNITY_EDITOR
[UnityEditor.MenuItem("QFramework/Example/13.AudioManager", false, 13)]
private static void MenuClicked()
{
UnityEditor.EditorApplication.isPlaying = true;
new GameObject("AudioExample")
.AddComponent<AudioExample>();
}
#endif
private void Start()
{
AudioManager.Instance.PlaySound("coin");
}
}
}
運行之後,結果與原來的一致。
OK,第一個播放音頻功能就有了 ,雖然問題有很多……,但是有了……
完善播放功能現在我們的示例中只播放了一次音頻,但是我們要播放兩次呢?
示例代碼改成如下:
QFramework/Example/13.AudioManager/AudioExample.cs
using UnityEngine;
namespace QFramework
{
public class AudioExample : MonoBehaviour
{
#if UNITY_EDITOR
[UnityEditor.MenuItem("QFramework/Example/13.AudioManager", false, 13)]
private static void MenuClicked()
{
UnityEditor.EditorApplication.isPlaying = true;
new GameObject("AudioExample")
.AddComponent<AudioExample>();
}
#endif
private void Start()
{
AudioManager.Instance.PlaySound("coin");
AudioManager.Instance.PlaySound("coin");
}
}
}
運行之後結果如下:
我們先看看播放聲音的代碼
public void PlaySound(string soundName)
{
gameObject.AddComponent<AudioListener>();
var audioSource = gameObject.AddComponent<AudioSource>();
var coinSound = Resources.Load<AudioClip>(soundName);
audioSource.clip = coinSound;
audioSource.Play();
}
確實是,每次播放的時候,都會 AddComponet<AudioListener\>();
這部分解決起來比較簡單。
只要每次都判斷一次當前 GameObject 是否有 AudioListener 就好了。
代碼如下:
private AudioListener mAudioListener;
public void PlaySound(string soundName)
{
if (!mAudioListener)
{
mAudioListener = gameObject.AddComponent<AudioListener>();
}
var audioSource = gameObject.AddComponent<AudioSource>();
var coinSound = Resources.Load<AudioClip>(soundName);
audioSource.clip = coinSound;
audioSource.Play();
}
這樣就沒有邏輯上的問題了。
大家注意一下, audioListener 不是 bool 變量,但是它卻可以直接在 if 語句上當做表達式判斷。這是因為 Unity 對所有的 UnityEngine.Object 類型做了一個運算符重載。像我們的 MonoBehaviour、GameObject、Transform 全部都是可以這樣做的,因為它們都繼承了 UnityEngine.Object。
到這裡我們再運行一次示例。運行之後沒有任何問題。
不過這個問題不大。
今天的內容就這些,我們下一篇再見。
轉載請註明地址:涼鞋的筆記:liangxiegame.com
訂閱全套專欄:liangxiegame.com