游戏模块化之声音模块

前置知识

1.每个场景有且只有一个Audio Listener
2.一个AudioSource 可以播放多种AudioClip
3.AudioSource有很多属性而且继承MonoBehavior,所以非常占用空间,所以少用

引出问题:
1.如何使用有限的AudioSouce播放无限个AudioClips
解决方案:
针对手游与vr进行的优化,默认加载三个AudioSource在AudioManager中.
如果想要播放音乐就把clip放入空闲的AudioSource中.
同时播放的clip如果超过了3个,那么就再次在AudioSource中添加一个AudioSource组件.
可通过命令清除空闲的组件以保证AudioSource不太占内存空间.

需求:

Audio管理器模块

设计图:

图片

代码实现:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SingleClip {

    AudioClip myClip;

    public SingleClip(AudioClip tempClip)
    {
        myClip = tempClip;
    }

    public void Play(AudioSource audio)
    {
        audio.clip = myClip;
        audio.Play();
    }

}

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

public class ClipsManager {

    string[] clipsName;

    public ClipsManager()
    {
        ReadConfig();
        LoadClips();
    }



    public void ReadConfig()
    {
        //地址
        var fileAddress = Path.Combine(Application.streamingAssetsPath, "AudioConfig.txt");
        //文件信息
        FileInfo fInfo0 = new FileInfo(fileAddress);
        //如果文件存在
        if (fInfo0.Exists)
        {
            //开启读取
            StreamReader r = new StreamReader(fileAddress);
            string tempLine = r.ReadLine();
            int lineCount = 0;
            
            if (int.TryParse(tempLine,out lineCount))
            {
                clipsName = new string[lineCount];
                for (int i = 0; i < lineCount; i++)
                {
                    tempLine = r.ReadLine();
                    string[] splits = tempLine.Split(" ".ToCharArray());
                    clipsName[i] =  splits[0];
                }
            }
            //关闭文件
            r.Close();
        }
    }


    SingleClip[] allSingleClip;

    public void LoadClips()
    {
        allSingleClip = new SingleClip[clipsName.Length];
        for (int i = 0; i < clipsName.Length; i++)
        {
            AudioClip tempClip =  Resources.Load<AudioClip>(clipsName[i]);
            SingleClip singleClip = new SingleClip(tempClip);
            allSingleClip[i] = singleClip;
        }
    }

    public SingleClip FindClipByName(string clipName)
    {
        for (int i = 0; i < this.clipsName.Length; i++)
        {
            if(clipName == this.clipsName[i])
            {
                return allSingleClip[i];
            }
        }
        return null;
    }

}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SourcesManager
{

    public SourcesManager(GameObject tempOwer)
    {
        ower = tempOwer;
        Initial();
    }

    List<AudioSource> allSources;

    GameObject ower;



    public void Initial()
    {
        allSources = new List<AudioSource>();
        for (int i = 0; i < 3; i++)
        {
            AudioSource source = ower.AddComponent<AudioSource>();
            allSources.Add(source);
        }
    }

    public AudioSource GerFreeAudio()
    {
        AudioSource source;
        for (int i = 0; i < allSources.Count; i++)
        {
            if (!allSources[i].isPlaying)
            {
                return allSources[i];
            }
        }
        source = ower.AddComponent<AudioSource>();
        allSources.Add(source);
        return source;
    }


    public void ReleaseFreeAudio()
    {
        List<AudioSource> freeSource = new List<AudioSource>();
        int freeCount = 0;
        for (int i = 0; i < allSources.Count; i++)
        {
            if (!allSources[i].isPlaying)
            {
                freeCount++;
                if (freeCount > 3)
                {
                    freeSource.Add(allSources[i]);
                }
            }
        }
        for (int j = 0; j < freeSource.Count; j++)
        {
            AudioSource source = freeSource[j];
            allSources.Remove(source);
            GameObject.Destroy(source);
        }
        freeSource.Clear();
        freeSource = null;
    }

    public void Stop(string audioName)
    {
        for (int i = 0; i < allSources.Count; i++)
        {
            if(allSources[i].isPlaying && audioName == allSources[i].clip.name)
            {
                allSources[i].Stop();
            }
        }
    }

}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudiosManager : MonoBehaviour {

    public AudiosManager Instance;

    SourcesManager sourcesManager;

    ClipsManager clipsManager;

    private void Start()
    {
        Instance = this;
        sourcesManager = new SourcesManager(gameObject);
        clipsManager = new ClipsManager();
    }

    public void Play(string audioName)
    {
        //取得一个空闲的AudioSource
        AudioSource tempSource = sourcesManager.GerFreeAudio();
        //根据名字的到clip
        SingleClip tempClip = clipsManager.FindClipByName(audioName);
        //播放
        tempClip.Play(tempSource);
    }

    public void Stop(string audioName)
    {
        sourcesManager.Stop(audioName);
    }

    public void ReleaseFreeAudio()
    {
        sourcesManager.ReleaseFreeAudio();
    }

    private void Update()
    {
        //测试
        if (Input.GetKeyDown(KeyCode.A))
        {
            Play("0");
        }
        if (Input.GetKeyDown(KeyCode.S))
        {
            Play("1");
        }
        if (Input.GetKeyDown(KeyCode.D))
        {
            Play("2");
        }
        if (Input.GetKeyDown(KeyCode.C))
        {
            ReleaseFreeAudio();
        }
        if (Input.GetKeyDown(KeyCode.X))
        {
            Stop("1");
        }

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值