在创建声音管理器之前,我们先创建一个空的类Manager用于保存所有的管理器单例,这样之后要用到管理器时,直接调用Manager类即可。每创建一个管理器类,都要在Manager类进行注册
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Manager
{
public static AudioManager m_Audio = AudioManager.Instance;
}
声音管理器完整代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioManager : ManagerBase<AudioManager>
{
// environment sound
private AudioSource envPlayer;
// sound effect
private AudioSource sePlayer;
// music
private AudioSource Player;
// Start is called before the first frame update
void Start()
{
envPlayer = gameObject.AddComponent<AudioSource>();
sePlayer = gameObject.AddComponent<AudioSource>();
Player = gameObject.AddComponent<AudioSource>();
// do not destroy audio manager when switching scene
GameObject.DontDestroyOnLoad(gameObject);
}
// play music
public void PlayMusic(string name, float volume = 1) {
AudioClip clip = Resources.Load<AudioClip>(name);
PlayMusic(clip, volume);
}
public void PlayMusic(AudioClip clip, float volume = 1) {
Player.volume = volume;
Player.clip = clip;
if (Player.isPlaying) {
Player.Stop();
}
Player.Play();
}
public void StopMusic() {
Player.Stop();
}
public void ChangeMusicVolume(float volume) {
Player.volume = volume;
}
// play environment sound
public void PlayEnvMusic(string name, float volume = 1) {
AudioClip clip = Resources.Load<AudioClip>(name);
PlayEnvMusic(clip, volume);
}
public void PlayEnvMusic(AudioClip clip, float volume = 1) {
envPlayer.volume = volume;
envPlayer.clip = clip;
if (envPlayer.isPlaying) {
envPlayer.Stop();
}
envPlayer.Play();
}
public void StopEnvMusic() {
envPlayer.Stop();
}
public void ChangeEnvMusicVolume(float volume) {
envPlayer.volume = volume;
}
// play sound effect
public void PlaySeSound(string name, float volume = 1) {
AudioClip clip = Resources.Load<AudioClip>(name);
PlaySeSound(clip, volume);
}
public void PlaySeSound(AudioClip clip, float volume = 1) {
sePlayer.PlayOneShot(clip, volume);
}
// play sound effect on an object
public void PlaySeSoundOnObject(string name, GameObject go, float volume = 1) {
AudioClip clip = Resources.Load<AudioClip>(name);
PlaySeSoundOnObject(clip, go, volume);
}
public void PlaySeSoundOnObject(AudioClip clip, GameObject go, float volume = 1) {
AudioSource player = go.GetComponent<AudioSource>();
if (player == null) {
player = go.AddComponent<AudioSource>();
}
player.volume = volume;
player.PlayOneShot(clip);
}
public override byte GetMessageType() {
return MessageType.Type_Audio;
}
}
代码解读:
1
// environment sound
private AudioSource envPlayer;
// sound effect
private AudioSource sePlayer;
// music
private AudioSource Player;
// Start is called before the first frame update
void Start()
{
envPlayer = gameObject.AddComponent<AudioSource>();
sePlayer = gameObject.AddComponent<AudioSource>();
Player = gameObject.AddComponent<AudioSource>();
// do not destroy audio manager when switching scene
GameObject.DontDestroyOnLoad(gameObject);
}
我们的声音管理器设置三个播放器,envPlayer,sePlayer,Player,分别用于管理游戏环境音乐,音效,和背景音乐。在Start方法中对三个管理器进行初始化,这样我们就不需要专门在游戏物体上挂载AudioSource组件。同时我们希望声音管理器不会在切换游戏场景时被删除,使用GameObject.DontDestroyOnLoad(gameObject);实现
2
// play music
public void PlayMusic(string name, float volume = 1) {
AudioClip clip = Resources.Load<AudioClip>(name);
PlayMusic(clip, volume);
}
public void PlayMusic(AudioClip clip, float volume = 1) {
Player.volume = volume;
Player.clip = clip;
if (Player.isPlaying) {
Player.Stop();
}
Player.Play();
}
public void StopMusic() {
Player.Stop();
}
public void ChangeMusicVolume(float volume) {
Player.volume = volume;
}
在播放音乐的方法PlayMusic中,我们考虑了两种情况:直接得到AudioClip对象,或者得到音乐名称在Resources文件夹下面查找对应的AudioClip。
如果直接得到AudioClip,我们在设置好音量和clip后判断一下播放器是否在播放其他音乐,如果是的话先关闭正在播放的音乐,然后开始播放新的clip。当然这里我们也可以根据具体游戏需求改变播放逻辑
如果传入的是音乐名,就从Resources加载对于音乐,然后调用第二个PlayMusic方法
同时我们设置了关闭音乐和改变音量方法
环境音的设置和背景音乐完全一样,故不再赘述
// play sound effect
public void PlaySeSound(string name, float volume = 1) {
AudioClip clip = Resources.Load<AudioClip>(name);
PlaySeSound(clip, volume);
}
public void PlaySeSound(AudioClip clip, float volume = 1) {
sePlayer.PlayOneShot(clip, volume);
}
// play sound effect on an object
public void PlaySeSoundOnObject(string name, GameObject go, float volume = 1) {
AudioClip clip = Resources.Load<AudioClip>(name);
PlaySeSoundOnObject(clip, go, volume);
}
public void PlaySeSoundOnObject(AudioClip clip, GameObject go, float volume = 1) {
AudioSource player = go.GetComponent<AudioSource>();
if (player == null) {
player = go.AddComponent<AudioSource>();
}
player.volume = volume;
player.PlayOneShot(clip);
}
对于音效设置,我们额外加入了方法PlaySeSoundOnObject。该方法是考虑到在3D游戏中,有些时候声音源并不是直接在玩家身上,而是远处的一个游戏物体上面,声音会随距离递减。PlaySeSoundOnObject方法传入要作为声音源的游戏物体,判断该物体是否存在AudioSource,如果不存在加上该组件,然后让该物体上面的AudioSource播放音效