当前位置:
首页 > Python基础教程 >
-
C#教程之音效系统
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);
}
}`
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式