Unity声音管理系统笔记

需求

  1. 在大厅、游戏场景都可以打开设置面板,设置音乐、音效的音量;
  2. 整个游戏所有的声源都按玩家设置的音量播放。这需要所有声源1.初始化时设置为玩家设置音量,2.玩家改变设置时所有声源改变音量;

分析

管理器在各个场景都存在,可以:

  1. 不继承MonoBehavior,就不能和AudioSource挂在一个对象,也不能通过拖指定音乐和UI音效AudioSource。如果在场景里建好AudioSource,让它用GameObject.Find()或transform.Find()找AudioSource,那么每个场景都要创建,容易漏掉。所以这条路最好让管理器新建对象,添加AudioSource。
  2. 继承MonoBehavior,可以拖了,每个场景都建一个,同理容易漏建,不是好方案。
  3. 继承MonoBehavior,并且DontDestroyOnLoad。

总之,手动在每个场景创建管理器不是好方案,如果又想拖,那么继承MonoBehavior,DontDestroyOnLoad可能是最好的方案。

附加声源的组件

我们发现AudioSource不能继承,那么就弄一个附加在AudioSourced的组件,它只干2件事

  1. 初始时把自己依附的声源设置为用户设置的音量;
  2. 用户设置音量变化时更新自己声源的音量;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MyFarm
{
    [RequireComponent(typeof(AudioSource))]
    public class AudioController:MonoBehaviour
    {
        AudioSource _audioSource;
        AudioSource audioSource
        {
            get
            {
                if(_audioSource == null)
                {
                    _audioSource = GetComponent<AudioSource>();
                }
                return _audioSource;
            }
        }
        private void Start()
        {
            UpdateVolume(MySettingsManager.Instance.settings.volume);
            MySettingsManager.Instance.onVolumeChanged += UpdateVolume;
        }
        private void OnDestroy()
        {
            MySettingsManager.Instance.onVolumeChanged -= UpdateVolume;
        }
        void UpdateVolume(float volume)
        {
            audioSource.volume = volume;
        }
    }
}

这是一个观察者模式的典型应用场景,因为

  1. 管理器去找各个声源比较麻烦,但还能做到;
  2. 更麻烦的是声源是随时可能出现、销毁的,如果让管理器维护声源Collection,管理器无法知道什么时候有声源出现、销毁,但是声源知道自己何时出现、销毁,且访问管理器很容易;

音量管理器(或者设置管理器)

玩家在设置面板修改音量>音量管理器音量值变化>触发音量变化委托>所有监听者更新。

旧版设计

维护字典

管理器维护一个字典,键是int InatanceID。

管理器怎么分清哪个是音乐,哪些是音效?可以把音乐AudioSource和UI音效AudioSource单独拖。其他通过FindObjectsByType(),再和音乐、UI音效AudioSource对比判断是其他AudioSource。

但是转换场景时要重新获得一遍场景所有的AudioSource。管理器怎么知道什么时候切换场景了

如果还有运行中创建AudioSource,声音管理器又怎么知道?创建AudioSource的脚本通知一下声音管理器?

走这条路,需要自己继承一个AudioSource,叫MyAudioSource,初始化时把自己加入管理器字典,销毁时移出字典。修改音量时遍历一遍字典。

或者修改音量也可以MyAudioSource监听管理器修改音量的事件。

然后发现AudioSource不允许继承。

那就还是通过各个引用AudioSource的脚本加入、移出字典。

只封装播放方法?

需要把项目所有的audioSource.Play()替换成自己封装的方法。先找到一个audioSource.Play(),再对Play()寻找引用,替换audioSource.Play()。

public void MyPlaySound(AudioSource audioSource){
        audioSource.volume=DataManager.Instance.settingsData.soundVolume;
        audioSource.Play();
    }

音乐在游戏开始运行时开始播放,需要在初始化、玩家改变音量时设置音量。各AudioSource知道自己是音乐、UI音效还是其他音效,也知道自己什么时候播放,无需关心场景有没有切换。

问题是环境音效,比如鸟叫,是不用调用Play的,从一开始就播放并且循环播放,也要设置为玩家设置的音量,并且玩家修改设置时要改变音量。

总结

要么维护字典,要么监听事件,且由各个引用AudioSource的脚本负责添加、移除。为此可以定义一个接口,强制

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值