14_音乐播放服务_字典缓存避免重复加载

首先在游戏根入口下创建空节点

F2重命名为BGAudio 作为播放 背景音乐的对象

在BGAudio对象上挂载组件 AudioSource

关掉PlayOnAwake

因为我们需要通过代码来控制音效

音量大小设置为0.5

Ctrl + d 再复制一份背景播放对象BGAudio

重命名为UIAudio 作为UI窗口操作的播放对象

创建脚本 AudioSvc.cs

编写脚本 音乐播放服务 很多地方需要用到 所以设置成单例 增加一个初始化方法

cs 复制代码
using UnityEngine;
//功能 : 音乐播放服务
public class AudioSvc : MonoBehaviour{
    public static AudioSvc Instance;
    public void InitSvc(){
        Instance = this;
        Debug.Log("Init AudioSvc...");
    }
}

在游戏根入口GameRoot.cs添加音乐播放服务的初始化函数

因为GameRoot.cs用到GetComponent<>()组件 所以需要将 AudioSvc.cs要挂载至GameRoot对象身上

继续编写音乐播放服务脚本AudioSvc.cs

对场景对象进行关联

拿到这两个组件之后我们就可以利用这两个组件来播放音效

这里我们需要资源服务ResSvc.cs的函数 所以在资源服务ResSvc.cs中添加函数

现在我们在项目中添加一个音乐资源

先在Resources文件夹下创建一个空文件命名为ResAudio

导入资源文件

继续编写代码 - 资源加载服务层ResSvc.cs

cs 复制代码
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; //异步加载 命名空间
//功能 : 资源加载服务
public class ResSvc : MonoBehaviour{
    #region 单例模式
    public static ResSvc Instance = null;
    #endregion
    public void InitSvc(){
        #region 单例模式
        Instance = this;
        #endregion
        Debug.Log("Init ResSvc...");
    }
    #region 【委托】更新回调 进度值
    Action prgCB = null;
    #endregion
    //自定义异步加载
    public void AsyncLoadScene(string sceneName,Action loaded) {
        #region 窗口基类的好处
        GameRoot.Instance.loadingWnd.SetWndState();
        #endregion
        //拿到异步操作
        AsyncOperation sceneAsync = SceneManager.LoadSceneAsync(sceneName);
        #region 【委托】更新回调 进度值
        //Lamd表达式
        prgCB = () =>{
            //当前加载进度
            float val = sceneAsync.progress;
            GameRoot.Instance.loadingWnd.SetProgress(val);
            if (val == 1){
                #region Loaded回调判断
                if (loaded != null)
                    loaded();
                #endregion
                #region 单例调用打开登录窗口
                //LoginSys.Instance.OpenLoginWnd();
                #endregion
                //当进度满后 进度值 置空
                prgCB = null;
                sceneAsync = null;
                GameRoot.Instance.loadingWnd.gameObject.SetActive(false);
            }
        };
        #endregion
    }
    #region 【委托】更新回调 进度值
    void Update(){
        if(prgCB != null)
            prgCB();
    }
    #endregion
    #region 音乐播放资源_字典
    Dictionary<string,AudioClip> adDic = new Dictionary<string,AudioClip>();
    public AudioClip LoadAudio(string path, bool cache = false) {
        AudioClip au = null;
        //检查路径是否存在 需要对资源进行加载
        //out的作用是 如果路径已经存在这个资源 那么out直接就返回了
        if (!adDic.TryGetValue(path, out au)) {
            au = Resources.Load<AudioClip>(path);
            //检查是否需要缓存 避免重复加载
            if (cache) {
                adDic.Add(path, au);
            }
        }
        return au;
    }
    #endregion
}

音乐播放服务层AudioSvc.cs

cs 复制代码
using UnityEngine;
//功能 : 音乐播放服务
public class AudioSvc : MonoBehaviour{
    public static AudioSvc Instance;
    //背景音乐播放对象
    public AudioSource bgAudio;
    //窗口音乐播放对象
    public AudioSource uiAudio;
    public void InitSvc(){
        Instance = this;
        Debug.Log("Init AudioSvc...");
    }
    //播放背景音乐
    public void PlayBGMusic(string name, bool isLoop) {
        //路径 与 缓存
        AudioClip audio = ResSvc.Instance.LoadAudio("ResAudio/" + name,true);
        //检查背景音乐没有了 或 背景音乐名字不是目标名字 (代表切换音乐)
        if (bgAudio.clip == null || bgAudio.clip.name != audio.name) {
            bgAudio.clip = audio;
            bgAudio.loop = isLoop;
            bgAudio.Play();
        }
    }
    //播放窗口操作音效
    public void PlayUIAudio(string name) {
        //路径 与 缓存
        AudioClip audio = ResSvc.Instance.LoadAudio("ResAudio/" + name, true);
        uiAudio.clip = audio;
        uiAudio.Play();
    }
}

这样我们就可以在 业务系统中调用了

我们需要定义一个常量

添加常量

cs 复制代码
using UnityEngine;
//功能 : 登陆注册业务系统
public class LoginSys : MonoBehaviour{
    #region 单例模式
    public static LoginSys Instance = null;
    #endregion
    #region 引用登录窗口
    public LoginWnd loginWnd;
    #endregion
    public void InitSys() {
        #region 单例模式
        Instance = this;
        #endregion
        Debug.Log("Init LoginSys...");
    }
    //进入登录界面
    public void EnterLogin() {
        //TODO
        //异步加载登录界面
        //并显示加载进度
        #region 调用ResSvc单例类
        ResSvc.Instance.AsyncLoadScene(Constans.SceneLogin,() => {
            #region 窗口基类的好处
            loginWnd.SetWndState();
            #endregion
            #region 调用音乐播放服务
            AudioSvc.Instance.PlayBGMusic(Constans.BGLogin,true);
            #endregion
        });
        #endregion
    }
}

运行项目

这样在运行时就可以听见背景音乐了

End.

相关推荐
向宇it1 小时前
【unity组件介绍】URP Decal Projector贴花投影器,将特定材质(贴花)投影到场景中的其他对象上。
游戏·3d·unity·c#·游戏引擎·材质
斯是 陋室10 小时前
在CentOS7.9服务器上安装.NET 8.0 SDK
运维·服务器·开发语言·c++·c#·云计算·.net
inwith11 小时前
C#语法基础总结(超级全面)(二)
开发语言·c#
不修×蝙蝠12 小时前
设计模式深度解析:单例、工厂、适配器与代理模式
单例模式·设计模式·代理模式·适配器模式·工厂
ヾChen15 小时前
13届蓝桥杯省赛程序设计试题
物联网·学习·蓝桥杯·c#
猪蹄手18 小时前
单例模式详细讲解
开发语言·c++·单例模式
画船听雨眠aa18 小时前
23种设计模式--#2单例模式
单例模式·设计模式
我是唐青枫19 小时前
C#.NET 泛型详解
开发语言·c#·.net
Yasin Chen20 小时前
C# StringBuilder源码分析
开发语言·c#
格林威21 小时前
Baumer工业相机堡盟工业相机如何通过YoloV8模型实现人物识别(C#)
开发语言·人工智能·数码相机·yolo·计算机视觉·c#