首页 > 其他分享 >Unity游戏框架设计之音频管理器

Unity游戏框架设计之音频管理器

时间:2024-04-30 15:37:43浏览次数:14  
标签:return target audioSource audioAssetPath 音频 Unity 管理器 null string

Unity游戏框架设计之音频管理器

简单介绍

在游戏中,主要的音频分为两种类型。第一种类型是 BGM(背景音乐),第二种类型是音效。BGM 的特点是音频持续时间长,一般在游戏中的同一时间内只能播放一个 BGM。音效的特点是音频持续时间短,一般在游戏中的同一时间内允许同时播放多个音效。

在下述代码中,实现了对 BGM 音量和音效音量的全局配置。玩家可以在游戏的设置 UI 中配置 BGM 音量和音效音量。同时实现了播放 BGM 和播放音效的功能,以及音频的生命周期方法。

代码设计

public class AudioManager : SingletonMono<AudioManager>
{
    private static AudioMixer _audioMixer;
    private static string _audioMixerGroupBGMPath;
    private static string _audioMixerGroupSoundsPath;
    private static string _bgmVolumeParameter;
    private static string _soundVolumeParameter;
    private readonly Dictionary<string, AudioClip> _audioClipSet = new();

    public static void Initialize(string audioMixerAssetPath, string audioMixerGroupBGMPath, string audioMixerGroupSoundsPath,
        string audioMixerBGMVolumeParameter, string audioMixerSoundsVolumeParameter)
    {
        _audioMixer = ResourceManager.Instance.LoadAsset<AudioMixer>(audioMixerAssetPath);
        _audioMixerGroupBGMPath = audioMixerGroupBGMPath;
        _audioMixerGroupSoundsPath = audioMixerGroupSoundsPath;
        _bgmVolumeParameter = audioMixerBGMVolumeParameter;
        _soundVolumeParameter = audioMixerSoundsVolumeParameter;
    }

    public void ConfigBGMVolume(float bgmVolume)
    {
        if (FloatUtils.IsEqualsTo(bgmVolume, 0f))
        {
            _audioMixer.SetFloat(_bgmVolumeParameter, -80);
            return;
        }
        _audioMixer.SetFloat(_bgmVolumeParameter, 5f / Mathf.Log10(2) * Mathf.Log10(bgmVolume));
    }

    public void ConfigSoundsVolume(float soundsVolume)
    {
        if (FloatUtils.IsEqualsTo(soundsVolume, 0f))
        {
            _audioMixer.SetFloat(_soundVolumeParameter, -80);
            return;
        }
        _audioMixer.SetFloat(_soundVolumeParameter, 5f / Mathf.Log10(2) * Mathf.Log10(soundsVolume));
    }

    public void PlayBGM(GameObject target, string audioAssetPath)
    {
        if (!_audioClipSet.ContainsKey(audioAssetPath))
        {
            LoadAsset(audioAssetPath);
        }
        SetBGM(target, audioAssetPath);
        PlayBGM(target);
    }

    public void PlaySound(GameObject target, string audioAssetPath)
    {
        if (!_audioClipSet.ContainsKey(audioAssetPath))
        {
            LoadAsset(audioAssetPath);
        }
        SetSounds(target, audioAssetPath);
        PlaySound(target);
    }

    public void PlaySound(GameObject target, List<string> audioAssetPathSet)
    {
        if (audioAssetPathSet.Count == 1)
        {
            PlaySound(target, audioAssetPathSet[0]);
            return;
        }
        foreach (string audioAssetPath in audioAssetPathSet)
        {
            if (!_audioClipSet.ContainsKey(audioAssetPath))
            {
                LoadAsset(audioAssetPath);
            }
        }
        foreach (string audioAssetPath in audioAssetPathSet)
        {
            SetSounds(target, audioAssetPath);
            PlaySound(target);
        }
    }

    public void Stop(GameObject target)
    {
        AudioSource audioSource = target.GetComponent<AudioSource>();
        if (audioSource == null)
        {
            return;
        }
        if (audioSource.clip == null)
        {
            return;
        }
        if (!audioSource.isPlaying)
        {
            return;
        }
        audioSource.Stop();
    }

    public void Pause(GameObject target)
    {
        AudioSource audioSource = target.GetComponent<AudioSource>();
        if (audioSource == null)
        {
            return;
        }
        if (audioSource.clip == null)
        {
            return;
        }
        if (!audioSource.isPlaying)
        {
            return;
        }
        audioSource.Pause();
    }

    public void UnPause(GameObject target)
    {
        AudioSource audioSource = target.GetComponent<AudioSource>();
        if (audioSource == null)
        {
            return;
        }
        if (audioSource.clip == null)
        {
            return;
        }
        if (audioSource.isPlaying)
        {
            return;
        }
        audioSource.UnPause();
    }

    private void LoadAsset(string audioAssetPath)
    {
        _audioClipSet[audioAssetPath] = ResourceManager.Instance.LoadAsset<AudioClip>(audioAssetPath);
    }

    private void UnloadAsset(string audioAssetPath)
    {
        if (!_audioClipSet.ContainsKey(audioAssetPath))
        {
            return;
        }
        AudioClip audioClip = _audioClipSet[audioAssetPath];
        if (audioClip == null)
        {
            return;
        }
        Destroy(audioClip);
        _audioClipSet.Remove(audioAssetPath);
    }

    private void SetBGM(GameObject target, string bgmAssetPath)
    {
        AudioSource audioSource = target.GetComponent<AudioSource>();
        if (audioSource == null)
        {
            audioSource = target.AddComponent<AudioSource>();
        }
        if (!_audioClipSet.ContainsKey(bgmAssetPath))
        {
            return;
        }
        AudioClip audioClip = _audioClipSet[bgmAssetPath];
        if (audioClip == null)
        {
            return;
        }
        audioSource.outputAudioMixerGroup = _audioMixer.FindMatchingGroups(_audioMixerGroupBGMPath)[0];
        audioSource.clip = audioClip;
    }

    private void SetSounds(GameObject target, string soundAssetPath)
    {
        AudioSource audioSource = target.GetComponent<AudioSource>();
        if (audioSource == null)
        {
            audioSource = target.AddComponent<AudioSource>();
        }
        if (!_audioClipSet.ContainsKey(soundAssetPath))
        {
            return;
        }
        AudioClip audioClip = _audioClipSet[soundAssetPath];
        if (audioClip == null)
        {
            return;
        }
        audioSource.outputAudioMixerGroup = _audioMixer.FindMatchingGroups(_audioMixerGroupSoundsPath)[0];
        audioSource.clip = audioClip;
    }

    private void PlayBGM(GameObject target)
    {
        AudioSource audioSource = target.GetComponent<AudioSource>();
        if (audioSource == null)
        {
            return;
        }
        if (audioSource.clip == null)
        {
            return;
        }
        if (audioSource.isPlaying)
        {
            return;
        }
        audioSource.playOnAwake = false;
        audioSource.loop = true;
        audioSource.Play();
    }

    private void PlaySound(GameObject target)
    {
        AudioSource audioSource = target.GetComponent<AudioSource>();
        if (audioSource == null)
        {
            return;
        }
        if (audioSource.clip == null)
        {
            return;
        }
        audioSource.playOnAwake = false;
        audioSource.loop = false;
        audioSource.PlayOneShot(audioSource.clip);
    }

    private void UnsetAudio(GameObject target)
    {
        AudioSource audioSource = target.GetComponent<AudioSource>();
        if (audioSource == null)
        {
            return;
        }
        audioSource.Stop();
        audioSource.clip = null;
    }
}

代码说明

(一)实现 BGM 和音效的音量大小的全局控制。

(二)实现播放 BGM 和播放音效的功能。

(三)实现对音频生命周期的控制,包括播放、暂停、恢复和停止操作。

后记

由于个人能力有限,文中不免存在疏漏之处,恳求大家斧正,一起交流,共同进步。

标签:return,target,audioSource,audioAssetPath,音频,Unity,管理器,null,string
From: https://www.cnblogs.com/kkelin/p/18168086

相关文章

  • Unity性能分析(一)流程与工具的使用
    性能分析工作流对于游戏开发是“必备”的,从基本的三方面开始:在修改之前分析:建立基准线在开发过程中分析:确保修改不会影响性能在修改后分析:证明修改产生了预期效果分析工具是开发者的实用工具之一,可以帮助开发者定位代码中的内存问题和性能瓶颈,也能帮助了解Unity引擎底层的运......
  • Unity性能分析(二)CPU/GPU分析
    设置每帧时间预算帧率(fps)并不是衡量游戏稳定体验的理想指标。考虑以下情况:在运行时的前0.75s内渲染了59帧。然后接下来的1帧需要0.25s才能渲染完毕。虽然是60fps,但实际上会让玩家感觉卡顿。这是需要设置帧时间预算的重要原因之一。这为您提供了一个目标,在对游戏进行分析和优化时......
  • Unity性能分析(三)内存分析
    Unity中有两种分析内存的方法:MemoryProfiler:内置的分析器,提供内存使用的基本信息。MemoryProfilerpackage:将package添加到项目中,更详细地分析内存使用情况。可以存储和比较快照查找内存泄漏,查看内存布局以查找内存碎片问题。确定物理RAM限制每个目标平台都有一个内存限......
  • Unity性能分析(四)Unity性能分析工具使用
    使用Profiler按照以下步骤开始使用UnityProfiler:在进行分析时,必须使用开发版本。File>BuildSettings>DevelopmentBuild。勾选AutoconnectProfile(可选)。注意:AutoconnectProfile会增加初始启动时间。如果不启用AutoconnectProfiler,可以随时手动连接正在运行的开发版......
  • Unity游戏框架设计之场景管理器
    Unity游戏框架设计之场景管理器简单介绍在游戏开发过程中,我们经常对Scene进行切换。为了不使场景切换时造成的游戏卡顿,可以Unity官方API利用协程的方式异步加载场景。同时,为提升Scene切换的玩家体验,我们经常会在场景切换的开始,先显示过渡UI,然后才对目标场景进行加载......
  • Unity游戏框架设计之任务管理器
    Unity游戏框架设计之任务管理器简单介绍在游戏开发中,我们可能会遇到下述需求。当角色的生命值减少时,我们需要让角色播放受伤动画,让系统播放角色受伤音效,将当前的新的生命值更新到UI上等等操作。如果在角色的代码中直接实现上述的操作,则将导致代码的高度耦合,不利于后期的维护和......
  • Unity游戏框架设计之消息管理器
    Unity游戏框架设计之消息管理器简单介绍消息管理器又可以称为任务管理器,主要解决延迟执行某些代码的问题。比如,我们希望一些代码可以延迟指定的时间后才执行,或者我们希望一些代码可以在固定的时间执行,又或者我们希望一些代码可以每隔一段时间就执行一次。消息管理器就是为了实现......
  • Unity游戏框架设计之协程管理器
    Unity游戏框架设计之协程管理器代码设计/**协程管理器*/publicclassCoroutineManager:SingletonMono<CoroutineManager>{/***创建CoroutineTask*/publicCoroutineTaskCreateCoroutine(IEnumeratorcoroutine,Action<bool>finishHandler......
  • Unity游戏框架设计之单例Mono
    Unity游戏框架设计之单例Mono简单介绍在编写Unity脚本的过程中,我们通常需要编写一些依赖于MonBehaviour生命周期且全局始终唯一的类,比如EventManager、TaskManager、ResourceManager和UIManager等等。我们可以基于单例模式,设计出名为SingletonMono的单例类,然后让拥......
  • Linux软件包管理器,RPM和YUM的区别
    RPMRPM(RedhatLinuxPacketManger)是RedHat公司随RedhatLinux推出的一个软件包管理器,通过它能够轻松实现Linux软件的安装。但是,需要手动解决软件包的依赖关系。YUMYUM(YellowdogUpdater,Modified)是一个Shell前端软件包管理器。基于RPM包管理器,能够从指定的服务器自动......