当前位置: 首页 > news >正文

广州网站设计推荐柚米建设通网站官网登录

广州网站设计推荐柚米,建设通网站官网登录,更改wordpress主题字体颜色,松江集团网站建设需求描述 在游戏开发中#xff0c;音频资源是不可或缺的#xff0c;通常情况下音频资源随机分布#xff0c;各个音频的操作和管理都是各自负责#xff0c;同时对于音频的很多操作逻辑都是大同小异的#xff0c;这就造成了许多冗余代码的堆叠#xff0c;除此之外在获取各类…需求描述 在游戏开发中音频资源是不可或缺的通常情况下音频资源随机分布各个音频的操作和管理都是各自负责同时对于音频的很多操作逻辑都是大同小异的这就造成了许多冗余代码的堆叠除此之外在获取各类音频资源的时候也会造成不必要的开销。所以解决资源分散的问题最直接的方式就是集中管理和分配通过统一的渠道和特有标识即可获取或操作对应的音频资源。所以本篇文章将围绕这个方案进行尝试。 功能描述 在Unity中我们导入的音频资源都会转换为AudioClip音频的设置和管理则由AudioSource负责AudioListener负责监听音频。我们可以在此基础上去封装从而打造一个音频管理器。 音频管理器负责管理音频信息以及操作音频比如音频信息的增加和删除音频的播放和暂停等 音频信息可以使用一个单独的实体类来记录用于记录AudioSource组件中的信息之所以单独用一个实体类来记录音频信息而不直接采用AudioSource主要是可以通过业务需求去动态调整所要记录的音频信息我们的实际开发中并非需要AudioSource中所有的信息有时候仅仅需要其中的一部分同时音频信息可能涉及存储直接采用AudioSource可能无法与已经开发好的存储系统相互兼容而实体类可以为其添加接口或继承来兼容存储系统 AudioSource组件的管理可以通过一个组件池进行管理我们知道AudioSource也是等同于一个音频实体类但是其同时也是一种组件组件同样作为一种资源通常情况下相比简单的实体类而言会带来更大的开销例如一个场景中有十个游戏对象有播放音频的需求那么按照传统情况就需要每个游戏对象挂载一个AudioSource组件但是实际运行中十个游戏对象并不一定需要同时播放音频它们或许都存在各自触发音频播放的条件我们只需要在游戏对象需要播放音频时为其分配一个AudioSource组件即可组件池则负责维护AudioSource组件的生产、获取和归还进而减少资源开销。 本质上AudioSource组件承担的工作就是记录音频信息和操作音频我们现在将记录工作分担给音频信息实体类而操作音频的工作则分担给音频管理器例如音频管理器的播放依旧是调用AudioSource的播放方法在播放之前由音频管理器去获取AudioSource组件并且为之配置音频信息其它的音频操作逻辑同理。 代码展示C# AudioManager.cs using System.Linq; using System; using System.Collections.Generic; using UnityEngine;namespace Tools.AudioManagerAPI {/// summary/// 音频管理器/// /summary[DisallowMultipleComponent]public class AudioManager : MonoBehaviour{[Header(必要属性)][Tooltip(音频总音量,默认为1(值属于[0,1]),该值将影响所有音频的音量,例如该值为0则所有音频音量变为原有音量的0%,若为1则所有音频音量保持不变,即该值将基于所有音频的当前音量进行影响,而不是直接统一所有音频的音量为该值)][Range(0, 1), SerializeField] private float TotalVolume 1;/// summary/// 音频总音量默认为1(值属于[0,1])/// para声明该值将影响所有音频的音量例如该值为0则所有音频音量变为原有音量的0%若为1则所有音频音量保持不变即该值将基于所有音频的当前音量进行影响而不是直接统一所有音频的音量为该值/para/// /summarypublic float mTotalVolume{get { return TotalVolume; }set{if (value 0 value 1 TotalVolume ! value){TotalVolume value;mTotalVolumeChangedEvents?.Invoke(value);}}}/// summary/// 是否启用音频信息覆盖默认为true/// /summarypublic bool mIsOverWrite { get isOverWrite; set isOverWrite value; }/// summary/// 音频管理器中所存储的音频数量/// /summarypublic int mCount { get audioInfos.Count; }/// summary/// 总音量更改事件回调/// /summarypublic event Actionfloat mTotalVolumeChangedEvents;/// summary/// 音频信息名称合集/// /summarypublic string[] mAudioInfoNames { get audioInfos.Keys.ToArray(); }private Dictionarystring, AudioInfo audioInfos;//音频信息集合private bool isInit;//是否完成了初始化private bool isOverWrite;//是否启用音频信息覆盖private static AudioSourcePool audioSourcePool AudioSourcePool.GetInstance();//AudioSource组件池/// summary/// 播放指定名称的音频/// parap_audioName音频名称/para/// /summarypublic void Play(string p_audioName){if (isInit){if (audioInfos.ContainsKey(p_audioName)){AudioInfo ai audioInfos[p_audioName];AudioSource v_audioSource audioSourcePool.Get(ai);ai.mAudioSource v_audioSource;ai.Play();}}}/// summary/// 播放指定名称的音频并开启立体声过渡/// parap_audioName音频名称/para/// para声明该方法要求已启用立体声过渡且已设置好立体声过渡的相关属性/para/// /summarypublic void PlayWithStereoTransition(string p_audioName){if (isInit){if (audioInfos.ContainsKey(p_audioName)){AudioInfo ai audioInfos[p_audioName];AudioSource v_audioSource audioSourcePool.Get(ai);ai.mAudioSource v_audioSource;StartCoroutine(ai.mStereoPanTransitionCoroutine);ai.Play();}}}/// summary/// 播放指定名称的音频并开启立体声过渡/// parap_audioName音频名称/para/// parap_stereoTransitionValues立体声过渡值集合/para/// parap_stereoTimeSpan立体声过渡每帧时间间隔/para/// /summarypublic void PlayWithStereoTransition(string p_audioName, float[] p_stereoTransitionValues, float p_stereoTimeSpan){if (isInit){if (audioInfos.ContainsKey(p_audioName)){AudioInfo ai audioInfos[p_audioName];AudioSource v_audioSource audioSourcePool.Get(ai);ai.mAudioSource v_audioSource;ai.mStereoTransition true;ai.mStereoTransitionValues p_stereoTransitionValues;ai.mStereoTransitionTimeSpan p_stereoTimeSpan;StartCoroutine(ai.mStereoPanTransitionCoroutine);ai.Play();}}}/// summary/// 暂停播放指定名称的音频/// parap_audioName音频名称/para/// /summarypublic void Pause(string p_audioName){if (isInit){if (audioInfos.ContainsKey(p_audioName)){AudioInfo ai audioInfos[p_audioName];StopCoroutine(ai.mStereoPanTransitionCoroutine);ai.Pause();audioSourcePool.Return(ai.mAudioSource);}}}/// summary/// 添加音频信息/// parap_audioInfo音频信息/para/// para声明1若启用了音频信息覆盖当存在相同名称的音频时新的音频信息将覆盖旧的音频信息/para/// para声明2默认启用了音频信息覆盖可通过mIsOverWrite属性设置禁用/para/// /summarypublic void AddAudioInfo(AudioInfo p_audioInfo){if (isInit) DoAddAudioInfo(p_audioInfo);}/// summary/// 删除音频信息/// parap_audioName音频名称/para/// para返回值若删除成功则返回true否则返回false/para/// /summarypublic bool DeleteAudioInfo(string p_audioName){if (isInit) return DoDeleteAudioInfo(p_audioName);return false;}private void Awake(){isInit false;if (InitParameters()) isInit true;}//添加音频信息的执行逻辑private void DoAddAudioInfo(AudioInfo p_audioInfo){if (p_audioInfo ! null !String.IsNullOrEmpty(p_audioInfo.mAudioName)){string v_audioName p_audioInfo.mAudioName;p_audioInfo.BindAudioManager(this);if (isOverWrite) audioInfos[v_audioName] p_audioInfo;else if (!audioInfos.ContainsKey(v_audioName)) audioInfos.Add(v_audioName, p_audioInfo);}}//删除音频信息的执行逻辑private bool DoDeleteAudioInfo(string p_audioName){if (!String.IsNullOrEmpty(p_audioName) audioInfos.ContainsKey(p_audioName)){audioInfos[p_audioName].BindAudioManager(null);return audioInfos.Remove(p_audioName);}return false;}//对音频管理器相关参数进行初始化private bool InitParameters(){audioInfos new Dictionarystring, AudioInfo();isOverWrite true;audioSourcePool.BindAudioManager(this); #if UNITY_EDITORforeach (AudioInfo ai in AudioInfos)DoAddAudioInfo(ai); #endifreturn true;}#if UNITY_EDITOR/// summary/// 在当前Inspector面板中的AudioInfos中的元素数量/// /summarypublic int mAudioInfoCount { get AudioInfos?.Length 0 ? AudioInfos.Length : 0; }[SerializeField] private AudioInfo[] AudioInfos;//存储Inspector面板中/// summary/// 在当前Inspector面板中的AudioInfos中添加一个元素/// /summarypublic void Add(){AudioInfo v_audioInfo new AudioInfo();if (AudioInfos?.Length 0){AudioInfo[] v_audioInfos new AudioInfo[AudioInfos.Length 1];AudioInfos.CopyTo(v_audioInfos, 0);v_audioInfos[v_audioInfos.Length - 1] v_audioInfo;AudioInfos new AudioInfo[v_audioInfos.Length];v_audioInfos.CopyTo(AudioInfos, 0);}else AudioInfos new AudioInfo[] { v_audioInfo };v_audioInfo.ValidateCheck();}/// summary/// 在当前Inspector面板中的AudioInfos中删除一个元素/// /summarypublic void Delete(int p_index){if (AudioInfos?.Length 1) AudioInfos Array.EmptyAudioInfo();else if (AudioInfos?.Length 1){AudioInfo[] v_audioInfos new AudioInfo[AudioInfos.Length - 1];int v_index 0;for (int i 0; i AudioInfos.Length; i){if (i ! p_index) v_audioInfos[v_index] AudioInfos[i];}AudioInfos new AudioInfo[v_audioInfos.Length];v_audioInfos.CopyTo(AudioInfos, 0);}}private void OnValidate(){foreach (AudioInfo audioInfo in AudioInfos){audioInfo?.ValidateCheck();}} #endif} } AudioInfo.cs using UnityEngine; using System.Collections; using System.Linq; using System;namespace Tools.AudioManagerAPI {/// summary/// 音频信息/// /summary[System.Serializable]public class AudioInfo{[Header(必要组件)][Tooltip(AudioClip组件), SerializeField] private AudioClip TheAudioClip;[Header(必要属性)][Tooltip(音频名称), SerializeField] private string AudioName;[Tooltip(音频音量,默认为1(值属于[0,1])), Range(0, 1), SerializeField] private float Volume 1;[Tooltip(音频播放速度,默认为1(值属于[-3,3])), Range(-3, 3), SerializeField] private float Pitch 1;[Tooltip(立体声位置,默认为0(值属于[-1,1]),若为-1则完全为左声道,若为1则完全为右声道), Range(-1, 1), SerializeField] private float StereoPan 0;[Tooltip(音频优先级,默认为128(值属于[0,256])), Range(0, 256), SerializeField] private int Priority 128;[Tooltip(是否在场景启动时进行播放,默认为true), SerializeField] private bool PlayOnAwake true;[Tooltip(是否循环播放,默认为false), SerializeField] private bool Loop;[Tooltip(是否忽略总音量影响,默认为false), SerializeField] private bool IgnoreTotalVolume;[Header(立体声过渡属性)][Tooltip(是否启用立体声过渡,默认为false), SerializeField] private bool StereoTransition;[Tooltip(立体声过渡的每帧时间间隔,默认为0.5(值属于[0.1,5])), Range(.1f, 5), SerializeField] private float StereoTransitionTimeSpan 0.5f;[Tooltip(立体声过渡值集合), SerializeField] private float[] StereoTransitionValues;/// summary/// 音频名称/// /summarypublic string mAudioName { get AudioName; set AudioName value; }/// summary/// 音频音量默认为1(值属于[0,1])/// /summarypublic float mVolume{get { return Volume; }set { if (value 0 value 1) Volume value; }}/// summary/// 音频播放速度默认为1(值属于[-3,3])/// /summarypublic float mPitch{get { return Pitch; }set { if (value -3 value 3) Pitch value; }}/// summary/// 立体声位置默认为0(值属于[-1,1])若为-1则完全为左声道若为1则完全为右声道/// /summarypublic float mStereoPan{get { return StereoPan; }set { if (value -1 value 1) StereoPan value; }}/// summary/// 音频优先级默认为128(值属于[0,256])/// /summarypublic int mPriority{get { return Priority; }set { if (value 0 value 256) Priority value; }}/// summary/// 是否在场景启动时进行播放默认为true/// /summarypublic bool mPlayOnAwake { get PlayOnAwake; set PlayOnAwake value; }/// summary/// 是否循环播放默认为false/// /summarypublic bool mLoop { get Loop; set Loop value; }/// summary/// 是否启用立体声过渡默认为false/// /summarypublic bool mStereoTransition { get StereoTransition; set StereoTransition value; }/// summary/// 立体声过渡的每帧时间间隔默认为0.5(值属于[0.1,5])/// /summarypublic float mStereoTransitionTimeSpan{get { return StereoTransitionTimeSpan; }set { if (value 0.1f value 5) StereoTransitionTimeSpan value; }}/// summary/// 立体声过渡值集合/// /summarypublic float[] mStereoTransitionValues{get StereoTransitionValues;set StereoTransitionValues value;}/// summary/// AudioSource组件/// /summarypublic AudioSource mAudioSource { get audioSource; set audioSource value; }/// summary/// 立体声过渡协程/// /summarypublic IEnumerator mStereoPanTransitionCoroutine { get stereoPanTransitionCoroutine; }/// summary/// 是否忽略总音量影响,默认为false/// /summarypublic bool mIgnoreTotalVolume { get IgnoreTotalVolume; set IgnoreTotalVolume value; }private AudioSource audioSource;//AudioSource组件private AudioManager audioManager;//音频管理器private bool isInit;//是否完成初始化private IEnumerator stereoPanTransitionCoroutine;//立体声过渡协程private float actualVolume;//实际音量private Actionfloat totalVolumeChangedEvent;//总音量更改事件对象/// summary/// 将指定的AudioSource组件信息记录在新的AudioInfo实例中并返回它/// parap_audioSource指定的AudioSource组件/para/// para返回值新的AudioInfo实例/para/// /summarypublic static AudioInfo Record(AudioSource p_audioSource){AudioInfo v_audioInfo new AudioInfo();if (p_audioSource ! null){v_audioInfo.TheAudioClip p_audioSource.clip;v_audioInfo.Volume p_audioSource.volume;v_audioInfo.Pitch p_audioSource.pitch;v_audioInfo.StereoPan p_audioSource.panStereo;v_audioInfo.Priority p_audioSource.priority;v_audioInfo.PlayOnAwake p_audioSource.playOnAwake;v_audioInfo.Loop p_audioSource.loop;v_audioInfo.audioSource p_audioSource;}return v_audioInfo;}public AudioInfo(){isInit false;InitToDefault();}/// summary/// 播放音频/// /summarypublic void Play(){if (audioSource ! null !audioSource.isPlaying){if (!IgnoreTotalVolume){if (actualVolume 0 || actualVolume 1) actualVolume Volume;audioSource.volume actualVolume;}else actualVolume -1;audioSource.Play();}}/// summary/// 暂停音频播放/// /summarypublic void Pause(){if (audioSource ! null audioSource.isPlaying){audioSource.Pause();audioSource.volume Volume;}}/// summary/// 绑定音频管理器/// parap_audioManager音频管理器/para/// para声明1若有需要可通过该方法将当前的AudioInfo与指定的音频管理器进行绑定/para/// para声明2绑定后将自动向指定的音频管理器添加当前的AudioInfo/para/// /summarypublic void BindAudioManager(AudioManager p_audioManager){audioManager p_audioManager;if (audioManager ! null){audioManager.mTotalVolumeChangedEvents - totalVolumeChangedEvent;audioManager.mTotalVolumeChangedEvents totalVolumeChangedEvent;}}/// summary/// 初始化为默认值/// /summarypublic void InitToDefault(){if (!isInit){TheAudioClip null;AudioName Audio;Volume 1;Pitch 1;StereoPan 0;StereoTransitionValues null;StereoTransitionTimeSpan 0.5f;Priority 128;StereoTransition false;PlayOnAwake true;Loop false;audioSource null;stereoPanTransitionCoroutine StereoPanTransition();totalVolumeChangedEvent (val) TotalVolumeChangedEvent(val);actualVolume -1;}}/// summary/// 将当前AudioInfo实例中的信息配置给指定的AudioSource组件/// parap_audioSource指定的AudioSource组件/para/// /summarypublic void ShareTo(AudioSource p_audioSource){if (p_audioSource ! null){p_audioSource.clip TheAudioClip;p_audioSource.volume Volume;p_audioSource.pitch Pitch;p_audioSource.panStereo StereoPan;p_audioSource.priority Priority;p_audioSource.playOnAwake PlayOnAwake;p_audioSource.loop Loop;}}/// summary/// 将指定的AudioSource组件信息存储在当前AudioInfo实例中/// parap_audioSource指定的AudioSource组件/para/// /summarypublic void SelfRecord(AudioSource p_audioSource){if (p_audioSource ! null){TheAudioClip p_audioSource.clip;Volume p_audioSource.volume;Pitch p_audioSource.pitch;StereoPan p_audioSource.panStereo;Priority p_audioSource.priority;PlayOnAwake p_audioSource.playOnAwake;Loop p_audioSource.loop;audioSource p_audioSource;}}// 总音量更改事件// p_totalVolume总音量// 若不忽略总音量影响通过调用该事件将基于总音量和当前音量换算实际音量数值// 当TotleVolume为0时实际音量为0;// 当TotleVolume为1或不属于[0,1)时实际音量为Volume;// 当TotleVolume属于(0,1)时实际音量为Volume * TotalVolumeprivate void TotalVolumeChangedEvent(float p_totalVolume){if (!IgnoreTotalVolume){if (p_totalVolume 0) actualVolume 0;else if (p_totalVolume 0 p_totalVolume 1) actualVolume Volume * p_totalVolume;else actualVolume Volume;//运行时修改AudioSource音量if (audioSource ! null) audioSource.volume actualVolume;}else actualVolume -1;}//立体声过渡协程private IEnumerator StereoPanTransition(){int currentIndex 0;while (true){if (audioSource null || !StereoTransition || StereoTransitionValues null || StereoTransitionValues.Length 0)yield break;audioSource.panStereo StereoTransitionValues[currentIndex];yield return new WaitForSeconds(StereoTransitionTimeSpan);currentIndex (currentIndex 1) % StereoTransitionValues.Length;if (currentIndex 0) StereoTransitionValues StereoTransitionValues.Reverse().ToArrayfloat();}}#if UNITY_EDITOR[NonSerialized] private bool isAudioClipLog;private bool isAudioNameLog;/// summary/// Inspector面板的数据更改检测/// /summarypublic void ValidateCheck(){AudioClipCheck();AudioNameCheck();}//AudioClip检测private void AudioClipCheck(){if (TheAudioClip null){if (!isAudioClipLog){Debug.LogWarning(Component: bcolororangeTheAudioClip/color/b is null.);isAudioClipLog true;}}else isAudioClipLog false;}//AudioName检测private void AudioNameCheck(){if (String.IsNullOrEmpty(AudioName)){if (!isAudioNameLog){Debug.LogWarning(Property: bcolororangeAudioName/color/b is empty.);isAudioNameLog true;}}else isAudioNameLog false;} #endif} } AudioSourcePool.cs  using System.Collections.Generic; using UnityEngine;namespace Tools.AudioManagerAPI {/// summary/// AudioSource组件池/// /summarypublic class AudioSourcePool{/// summary/// 空闲的AudioSource数量/// /summarypublic int mFreeCount { get audioSources.Count; }private StackAudioSource audioSources;//AudioSource组件集合private AudioManager audioManager;//AudioManager组件private AudioInfo defaultAudioInfo;//默认的AudioInfo/// summary/// 获取实例单例模式/// /summarypublic static AudioSourcePool GetInstance(){return Handler.instance;}/// summary/// 绑定音频管理器/// parap_audioManager音频管理器/para/// /summarypublic void BindAudioManager(AudioManager p_audioManager){if (p_audioManager ! null) audioManager p_audioManager;}/// summary/// 获取AudioSource组件/// para返回值AudioSource组件/para/// /summarypublic AudioSource Get(){return DoGet();}/// summary/// 获取AudioSource组件并按照指定的AudioInfo为之配置属性/// parap_audioInfo指定的AudioInfo/para/// para返回值AudioSource组件/para/// /summarypublic AudioSource Get(AudioInfo p_audioInfo){AudioSource v_audioSource DoGet();p_audioInfo?.ShareTo(v_audioSource);return v_audioSource;}/// summary/// 归还指定的AudioSource组件/// parap_audioSource指定的AudioSource组件/para/// /summarypublic void Return(AudioSource p_audioSource){if (p_audioSource ! null){CleanAudioSource(p_audioSource);audioSources.Push(p_audioSource);}}class Handler{public static AudioSourcePool instance new AudioSourcePool();}private AudioSourcePool(){audioSources new StackAudioSource();defaultAudioInfo new AudioInfo();}//获取AudioSource组件的执行逻辑private AudioSource DoGet(){if (audioManager null) return null;AudioSource v_audioSource null;while (v_audioSource null){if (audioSources.Count 0) GenerateAudioSource();v_audioSource audioSources.Pop();}return v_audioSource;}//生成AudioSource组件private void GenerateAudioSource(){if (audioManager?.gameObject ! null){AudioSource v_audioSource audioManager.gameObject.AddComponentAudioSource();audioSources.Push(v_audioSource);}}//清洗AudioSource组件private void CleanAudioSource(AudioSource p_audioSource){defaultAudioInfo.ShareTo(p_audioSource);}} } NumberRange.cs using System.Collections.Generic; using System.Linq;namespace Tools.AudioManagerAPI {/// summary/// 数值范围数组工具类/// /summarypublic static class NumberRange{/// summary/// 获取指定范围内指定步长的Float数值数组/// parap_start:起始值/para/// parap_end:终点值/para/// parap_step:步长值/para/// para[ContainsEnd]:是否包括终点值,默认为false/para/// para返回值:Float[]/para/// /summarypublic static float[] FloatRange(float p_start, float p_end, float p_step, bool ContainsEnd false){if (!ContainsEnd) return DoFloatRange(p_start, p_end, p_step).ToArray();else{Listfloat result DoFloatRange(p_start, p_end, p_step).ToList();result.Add(p_end);return result.ToArray();}}//获取指定范围内指定步长的Float数值数组的执行逻辑static IEnumerablefloat DoFloatRange(float p_start, float p_end, float p_step){for (float i p_start; i p_end; i p_step){yield return i;}}} } 界面展示 演示效果 自定义Unity组件AudioManager 资源下载 GitHub_AudioManager    百度网盘 如果这篇文章对你有帮助请给作者点个赞吧
http://www.dnsts.com.cn/news/170746.html

相关文章:

  • 铜仁建设集团招聘信息网站修改目录wordpress
  • html5网站建设基本流程做商城网站系统
  • 郑州高端建站国内品牌设计公司
  • 网站建设价格济南网站建设 前沿文章
  • 网站title修改门户网站等保二级建设方案
  • 温州网站网站建设做网站设计的价格
  • 网站前端wordpress sql 导入
  • 如何快速新建一个网站抵押网站建设方案
  • 网站建设营销策划书广州做模板网站的公司
  • 产品网站策划书方案整站下载器 安卓版
  • 云南网站建设专家中国企业网聚焦中原
  • 上传网站到虚拟主机wordpress图片放七牛云
  • 如何自己建设一个网站优惠卷网站怎么做推广
  • 网站开发合作协议书网站内容管理系统 下载
  • 开源建站工具app推广方案策划
  • 如何建设手机网站首页产品结构设计
  • 网站建设业务饱和了吗站长工具seo综合查询怎么关闭
  • 现在.net做网站的多吗创新驱动发展战略的意义
  • 武安城乡建设网站淘宝客不建立网站怎么做
  • 北京网站设计公司招聘信息女生学网站设计
  • 北京网站建设厂家网页显示站点不安全
  • 免费企业网站模板htmlwordpress登录logo
  • 深圳flash网站建设xxx网站建设与优化推广
  • 外国网站 dns解析失败网站查询ip解析
  • 品牌网站设计提案徐州免费网站建设模板
  • 网站建设公司不能备案吗园岭网站建设
  • 做网站建设的销售薪水个人网站有哪些板块
  • 德阳市住房和城乡建设局网站首页做网站发现是传销
  • 编程scratch网站用ps做班级网站
  • 昌平建设网站优设网官方网