草庐IT

Unity 音频管理框架

heaventianjianke 2023-11-29 原文

AudioPlayManager

使用AudioPlayManager管理AuidoSourceManager和AudioClipManager。

提供一次性播放(播放完毕就结束)。

提供循环播放,返回SingleAudioClip,使用返回的SingleAudioClip停止播放。

using UnityEngine;

public class AudioPlayManager : MonoBehaviour
{
    public static AudioPlayManager instance;

    private AudioSourceManager audioSourceManager;
    private AudioClipManager audioClipManager;
    
    private void Start()
    {
        instance = this;
        audioSourceManager = new AudioSourceManager(gameObject);
        audioClipManager = new AudioClipManager();
    }

    private void Update()
    {
        audioSourceManager.ReleaseFreeAudioSource();
    }

    /// <summary>
    /// 播放音频(一次)
    /// </summary>
    /// <param name="audioClipName"></param>
    public void PlayOnceAudio(string audioClipName)
    {
        AudioSource tempAudioSource = audioSourceManager.FindFreeAudioSource();
        SingleAudioClip tempSingleAudioClip = audioClipManager.FindSingleAudioClip(audioClipName);
        
        tempSingleAudioClip.Initialize(tempAudioSource);
        
        tempSingleAudioClip.PlayAudio();
    }

    /// <summary>
    /// 播放音乐(需要调用StopPlay关闭)
    /// </summary>
    /// <param name="audioClipName"></param>
    public SingleAudioClip PlayAudio(string audioClipName)
    {
        AudioSource tempAudioSource = audioSourceManager.FindFreeAudioSource();
        SingleAudioClip tempSingleAudioClip = audioClipManager.FindSingleAudioClip(audioClipName);
        
        tempSingleAudioClip.Initialize(tempAudioSource);
        
        tempSingleAudioClip.PlayAudio();

        return tempSingleAudioClip;
    }
}

AudioSourceManager

管理所有AudioSource组件,控制AudioSource组件的数量。

分配用于播放的AudioSource,释放多余的AudioSource。

using System.Collections.Generic;
using UnityEngine;

public class AudioSourceManager
{
    private List<AudioSource> _audioSources;

    private GameObject playLocation;

    public AudioSourceManager(GameObject playLocation)
    {
        this.playLocation = playLocation;
        Initial();
    }
    
    /// <summary>
    /// 初始化
    /// </summary>
    private void Initial()
    {
        _audioSources = new List<AudioSource>();
        
        // 初始化三个AudioSource
        for (int i = 0; i < 3; i++)
        {
            _audioSources.Add(playLocation.AddComponent<AudioSource>());
        }
    }

    /// <summary>
    /// 找到空闲的AudioSource
    /// </summary>
    /// <returns></returns>
    public AudioSource FindFreeAudioSource()
    {
        for (int i = 0; i < _audioSources.Count; i++)
        {
            if (!_audioSources[i].isPlaying)
            {
                return _audioSources[i];
            }
        }
        
        // 没有空闲的AudioSource,创建新的AudioSource
        AudioSource tempSource = playLocation.AddComponent<AudioSource>();
        
        // 添加
        _audioSources.Add(tempSource);

        return tempSource;
    }

    /// <summary>
    /// 释放多余的AudioSource【大于3个】
    /// </summary>
    public void ReleaseFreeAudioSource()
    {
        int freeCount = 0;

        List<AudioSource> tempSources = new List<AudioSource>();
        
        // 记录有多少AudioSource没有播放
        for (int i = 0; i < _audioSources.Count; i++)
        {
            if (!_audioSources[i].isPlaying)
            {
                // 如果空闲AudioSource大于3个
                if (++freeCount>3)
                {
                    tempSources.Add(_audioSources[i]);
                }
            }
        }

        // 释放多余的AudioSource
        for (int i = 0; i < tempSources.Count; i++)
        {
            _audioSources.Remove(tempSources[i]);
            GameObject.Destroy(tempSources[i]);
        }
        
        // 释放临时List<>
        tempSources.Clear();
        tempSources = null;
    }
}

AudioClipManager

管理所有的音频文件。

初始化时从txt文档中获取所有音频assetbundle名称,再从assetbundle中获取所有的音频。

提供通过音频名称获取包装成的SingleAudioClip

using System.IO;
using UnityEngine;

public class AudioClipManager
{
    private string[] audioClipNames;

    private SingleAudioClip[] singleAudioClips;

    public AudioClipManager()
    {
        Initial();
    }

    private void Initial()
    {
        ReadAudioClipName();
        LoadAudioClip();
    }

    /// <summary>
    /// 从txt文件中读取AudioClipName
    /// </summary>
    private void ReadAudioClipName()
    {
        FileStream fs = new FileStream(Application.streamingAssetsPath+"/AudioClips.txt", FileMode.Open, FileAccess.Read, FileShare.None);
        StreamReader sr = new StreamReader(fs, System.Text.Encoding.Default);
        if (sr == null) 
            return;
        
        // 读取第一行
        string clips = sr.ReadLine();

        int clipCount = -1;

        if (int.TryParse(clips, out clipCount))
        {
            // 初始化audioClipNames
            audioClipNames = new string[clipCount];
            
            for (int i = 0; i < clipCount; i++)
            {
                audioClipNames[i] = sr.ReadLine().Split('|')[0];
            }
        }
        
        sr.Close();
    }

    /// <summary>
    /// 加载AudioClip
    /// </summary>
    private void LoadAudioClip()
    {
        // 初始化
        singleAudioClips = new SingleAudioClip[audioClipNames.Length];
        
        for (int i = 0; i < audioClipNames.Length; i++)
        {
            // 加载
            // AudioClip tempClip = Resources.Load<AudioClip>(audioClipNames[i]);
            AudioClip tempClip = ResourceAndDataManager.Instance.ObtainAudioClip(audioClipNames[i]);
            
            // 存储
            singleAudioClips[i] = new SingleAudioClip(tempClip);
        }
    }

    /// <summary>
    /// 通过AudioClipName获取SingleAudioClip
    /// </summary>
    /// <param name="audioClipName"></param>
    /// <returns></returns>
    public SingleAudioClip FindSingleAudioClip(string audioClipName)
    {
        for (int i = 0; i < audioClipNames.Length; i++)
        {
            // 如果找到
            if (audioClipNames[i].Equals(audioClipName))
            {
                return singleAudioClips[i];
            }
        }
        
        // 没有找到
        return null;
    }
}

SingleAudioClip

包装AudioSource和AudioClip,提供播放和停止播放方法。

using UnityEngine;

public class SingleAudioClip
{
    private AudioClip audioClip;
    private AudioSource audioSource;

    public SingleAudioClip(AudioClip audioClip)
    {
        this.audioClip = audioClip;
    }

    /// <summary>
    /// 初始化
    /// </summary>
    /// <param name="audioSource"></param>
    public void Initialize(AudioSource audioSource)
    {
        audioSource.clip = audioClip;
        this.audioSource = audioSource;
    }

    /// <summary>
    /// 播放AudioClip
    /// </summary>
    public void PlayAudio()
    {
        audioSource.Play();
    }

    /// <summary>
    /// 关闭AudioClip
    /// </summary>
    public void StopAudio()
    {
        audioSource.Stop();
    }
}

有关Unity 音频管理框架的更多相关文章

  1. ruby - i18n Assets 管理/翻译 UI - 2

    我正在使用i18n从头开始​​构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在ruby​​onrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi

  2. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

  3. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  4. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  5. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  6. unity---接入Admob - 2

    目录1.AdmobSDK下载地址2.将下载好的unityPackagesdk导入到unity里​编辑 3.解析依赖到项目中

  7. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  8. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  9. ruby - (Ruby || Python) 窗口管理器 - 2

    我想用这两种语言中的任何一种(最好是ruby​​)制作一个窗口管理器。老实说,除了我需要加载某种X模块外,我不知道从哪里开始。因此,如果有人有线索,如果您能指出正确的方向,那就太好了。谢谢 最佳答案 XCB,X的下一代API使用XML格式定义X协议(protocol),并使用脚本生成特定语言绑定(bind)。它在概念上与SWIG类似,只是它描述的不是CAPI,而是X协议(protocol)。目前,C和Python存在绑定(bind)。理论上,Ruby端口只是编写一个从XML协议(protocol)定义语言到Ruby的翻译器的问题。生

  10. ruby-on-rails - 事件管理员和自定义方法 - 2

    这是我在ActiveAdmin中的自定义页面ActiveAdmin.register_page"Settings"doaction_itemdolink_to('Importprojects','settings/importprojects')endcontentdopara"Text"endcontrollerdodefimportprojectssystem"rakedataspider:import_projects_ninja"para"OK"endendend我想做的是,当我单击“导入项目”按钮时,我想在Controller中执行rake任务。但是我无法访问该方法。可能是什

随机推荐