2025Unity超详细《坦克大战3D》项目实战案例(上篇)——UI搭建并使用和数据持久化(附资源和源代码)
一、需求分析
1.项目所需具备前提知识
2.核心需求框架
3.详细功能需求
(一)UI 功能需求
(二)数据存储功能需求
(三)游戏核心逻辑功能需求
二、场景搭建
1.导入素材
2.个性化搭建
三、开始界面面板
2.核心功能说明
3.开始界面面板:BeginPanel
4.核心功能说明
四、设置面板实现
1.设置面板:SettingPanel
2.功能说明
3.开始面板完善:BeginPanel 更新
五、音乐数据管理
1.音乐数据类:MusicData
2.说明
3.游戏数据管理器:GameDataMgr
4.核心功能说明
5.设置面板完善:SettingPanel
6.核心更新说明
六、排行榜的UI搭建与使用
1.开始面板的完善
2.排行榜面板(RankPanel)
3.说明
七、排行榜数据系统与面板完善
1.单条排行榜数据:RankInfo类
2.排行榜列表容器:RankList类
3.游戏数据管理器完善扩展:GameDataMgr类
4.核心扩展说明
5.排行榜面板完善:RankPanel
6.功能说明
7.实现流程与原理
八、背景音乐管理系统
1.背景音乐管理类:BKMusic
2.核心功能说明
3.游戏数据管理器更新:GameDataMgr
4.核心更新说明
九、资源以及源代码
1.资源(切勿商用)
2.源代码
演示
一、需求分析
1.项目所需具备前提知识
(1)Unity :理解 Unity 编辑器操作、场景搭建、游戏对象管理等核心基础。
(2)数据持久化:能够通过 PlayerPrefs 实现数据的存储与读取。
(3)UI 开发:具备使用 GUI 创建游戏界面、添加交互控件的能力。
2.核心需求框架
(1)UI 功能
(2)数据存储功能
(3)游戏核心逻辑功能
3.详细功能需求
(一)UI 功能需求
8 个 UI 面板脚本,同时提取 1 个基类脚本封装所有 UI 面板的共同点
(1)基类脚本:提取所有 UI 面板的共性逻辑,如面板的显示 / 隐藏控制、通用控件初始化、基础交互事件绑定等,为 7 个功能面板提供基础支撑。
(2)开始界面面板:包含 “开始游戏”“游戏设置”“退出游戏” 三个核心按钮,点击对应按钮可触发进入游戏、打开设置界面、退出游戏(退出时需提示 “此时退出游戏成绩将丢失”)的操作,是玩家进入游戏的入口界面。
(3)游戏界面面板:实时更新游戏关键信息,包括游戏时间、坦克血量、玩家分数,同时配置退出游戏的关键控件及监听函数,玩家可通过该面板直观掌握游戏进度与自身状态。
(4)游戏设置面板:核心功能为控制音视频相关数据,提供音乐、音效的开关控制及音量调节功能,玩家可根据自身需求调整游戏音频输出,提升游戏体验。
(5)游戏失败界面面板:当玩家坦克被摧毁时触发显示,界面提示 “很遗憾,您的坦克已被摧毁”,同时提供 “重来”“返回上一级”“再次挑战” 按钮,支持玩家重新开始游戏或返回上级菜单。
(6)游戏胜利界面面板:玩家通关时显示,提示 “恭喜通关”,并提供用户名输入框与 “确定” 按钮,玩家输入用户名后点击确定,即可将本次通关成绩计入排行榜。
(7)排行榜面板:以表格形式展示玩家排名信息,表格包含 “排名”“玩家名”“分数”“通关时间” 四列,默认展示 10 个排名位置,未填充的位置标注 “虚位以待”,玩家可在该面板查看历史优秀成绩,同时支持 “返回上一级” 操作。
(8)功能面板:整合游戏过程中的辅助功能控件与监听函数,为其他功能面板提供交互支持,确保各界面操作逻辑连贯。
(二)数据存储功能需求
通过设计 “数据管理类” 统一管理游戏数据,实现关键信息的持久化存储,确保玩家设置与游戏成绩不丢失
(1)音效设置信息存储:记录背景音乐、音效的开关状态及音量大小数据,玩家调整音效设置后,数据管理类通过 PlayerPrefs 将设置信息存储,下次启动游戏时自动加载上次设置,无需重复调整。
(2)排行榜信息存储:存储排行榜单条数据(包含玩家名字、分数、通关时间),形成排行榜数据列表。当玩家通关并输入用户名后,数据管理类将新成绩与历史成绩对比排序,更新排行榜并存储,确保排行榜信息实时、准确。
(三)游戏核心逻辑功能需求
(1)坦克类设计:提取所有坦克的共同点,创建 “坦克基类”,包含坦克血量、移动速度、开火间隔时间等基础属性,以及移动、开火、受击等通用方法;在此基础上设计 “敌方移动坦克” 子类,处理敌方坦克的简单 AI 逻辑(如自动移动、攻击)与怪物相关行为,区分玩家坦克与敌方坦克的功能差异。
(2)战斗与奖励逻辑:
【1】战斗机制:玩家坦克可装备武器,武器存在开火间隔时间限制,发射的子弹命中敌方坦克或障碍物时触发相应碰撞处理;敌方坦克被摧毁后可能生成奖励对象,玩家坦克获取奖励可触发属性加成(如血量奖励)或武器升级(如切换特殊子弹)。
【2】奖励处理:场景中设置可获取的武器奖励对象与属性临时奖励对象,玩家坦克接触奖励对象后触发领取逻辑,实时更新自身属性或武器状态,增强游戏策略性与趣味性。
(3)场景与视角逻辑:配置小地图摄像机,实现摄像机跟随玩家坦克移动的功能,同时在小地图中标记玩家坦克、敌方坦克、奖励对象等关键物体信息,帮助玩家掌握整个战场布局,提升游戏操作体验。
(4)得分与死亡逻辑:玩家摧毁敌方坦克、获取奖励时触发得分逻辑,实时累计并更新分数;当玩家坦克血量为 0 时触发死亡逻辑,跳转至游戏失败界面,结束当前游戏进程。
二、场景搭建
1.导入素材
2.个性化搭建
(1)从导入的资源中,搭建个性化的场地
(2)从导入的GUI预制体中,搭建个性化的UI界面,如上图所示:
三、开始界面面板
1.通用面板基类:BasePanel<T>
实现一个泛型基类 BasePanel<T>:
(1)
为所有 UI 面板提供单例管理
(2)显示 / 隐藏基础功能,避免重复编码。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class BasePanel<T> : MonoBehaviour where T:class
{//两个关键的静态成员//私有的静态成员变量(申明)private static T instance;//公共的静态成员属性或者方法(获取)public static T Instance => instance;private void Awake(){//在Awake中初始化的 原因是//我们的面板脚本 在场景上 肯定只会挂载一次//那么我们可以在这个脚本的生命周期函数的Awake中//直接记录场景上 唯一的这个脚本instance = this as T;}public virtual void ShowMe(){this.gameObject.SetActive(true);}public virtual void HideMe(){this.gameObject.SetActive(false);}
}
2.核心功能说明
(1)单例模式实现:通过静态私有变量 instance
与公开属性 Instance
,确保每个面板在场景中只有一个实例,外部可通过 XXXPanel.Instance
直接访问(如后续的 BeginPanel.Instance
)。
(2)生命周期初始化:在 Awake
方法中完成单例赋值,因为 Awake
在脚本生命周期中仅执行一次,且早于 Start
,能保证面板实例在使用前完成初始化。
(3)基础显示 / 隐藏接口:提供 ShowMe()
(激活面板)和 HideMe()
(隐藏面板)两个虚方法,子类可根据需要重写(如添加动画过渡),当前保持基础功能。
3.开始界面面板:BeginPanel
BeginPanel
继承自 BasePanel<BeginPanel>
,是游戏启动后第一个交互界面,负责 “开始游戏”“设置”“退出”“排行榜” 等核心操作入口。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;public class BeginPanel : BasePanel<BeginPanel>
{//首先声明公共的成员变量 来关联各个控件public CustomGUIButton btnBegin;public CustomGUIButton btnSetting;public CustomGUIButton btnQuit;public CustomGUIButton btnRank;// Start is called before the first frame updatevoid Start(){//监听一次按钮点击过后要做什么btnBegin.clickEvent += () =>{//切换场景SceneManager.LoadScene("GameScene");};btnSetting.clickEvent += () =>{//打开设置面板};btnQuit.clickEvent += () =>{//退出游戏Application.Quit();};btnRank.clickEvent += () =>{//打开排行榜面板};}
}
4.核心功能说明
(1)控件关联:声明 4 个 CustomGUIButton
类型的公共变量(btnBegin
/btnSetting
/btnQuit
/btnRank
),需在 Unity Inspector 面板中手动将 UI 按钮拖入对应字段,完成脚本与控件的绑定。
(2)按钮点击事件:在 Start
方法中为每个按钮绑定点击逻辑(基于自定义按钮的 clickEvent
事件):
- 开始游戏(btnBegin):通过
SceneManager.LoadScene("GameScene")
加载游戏主场景(需确保 “GameScene” 已在 Build Settings 中添加); - 退出游戏(btnQuit):通过
Application.Quit()
关闭游戏(打包后生效,Editor 模式下需额外处理可参考后续扩展); - 设置(btnSetting) 与 排行榜(btnRank):当前预留接口,后续可添加
SettingPanel.Instance.ShowMe()
与RankPanel.Instance.ShowMe()
实现面板切换。
四、设置面板实现
1.设置面板:SettingPanel
设置面板用于管理游戏中的音乐、音效等配置,继承自通用基类BasePanel<SettingPanel>
,实现基本的音视频设置功能。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SettingPanel : BasePanel<SettingPanel>
{//1. 声明成员变量 关联控件public CustomGUISlider sliderMusic; // 音乐音量滑块public CustomGUISlider sliderSound; // 音效音量滑块public CustomGUIToggle togMusic; // 音乐开关public CustomGUIToggle togSound; // 音效开关public CustomGUIButton btnClose; // 关闭按钮// Start is called before the first frame updatevoid Start(){//2. 监听对应的事件 处理逻辑sliderMusic.changeValue += (value) =>{// 处理音乐音量变化};sliderSound.changeValue += (value) =>{// 处理音效音量变化};togMusic.changeValue += (value) =>{// 处理音乐开关状态变化};togSound.changeValue += (value) =>{// 处理音效效开关状态变化};btnClose.clickEvent += () =>{// 隐藏当前设置面板HideMe();// 重新显示开始面板BeginPanel.Instance.ShowMe();};// 初始隐藏设置面板HideMe();}
}
2.功能说明
(1)控件关联:通过公共变量关联 4 个核心控件(2 个滑块、2 个开关、1 个按钮),需在 Unity Inspector 中手动绑定对应 UI 元素。
(2)事件绑定:
- 音量滑块(
sliderMusic
/sliderSound
):通过changeValue
事件监听数值变化,预留音乐 / 音效音量调节逻辑接口; - 开关控件(
togMusic
/togSound
):通过changeValue
事件监听开关状态,预留音乐 / 音效启用 / 禁用逻辑接口; - 关闭按钮(
btnClose
):点击后隐藏当前面板(HideMe()
),并重新显示开始面板(BeginPanel.Instance.ShowMe()
),实现面板切换。
(3)初始状态:在Start
方法末尾调用HideMe()
,确保游戏启动时设置面板默认隐藏。
3.开始面板完善:BeginPanel 更新
......
btnSetting.clickEvent += () =>{// 打开设置面板SettingPanel.Instance.ShowMe();// 隐藏当前开始面板(避免点击穿透)HideMe();};
......
在btnSetting
的点击事件中,通过SettingPanel.Instance.ShowMe()
显示设置面板,并调用HideMe()
隐藏自身,避免两个面板同时显示导致的交互冲突(如点击穿透)。
五、音乐数据管理
1.音乐数据类:MusicData
该类用于定义需要存储的音乐相关配置数据,是数据持久化的基础模型。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 音效数据类 用于存储音乐设置相关的信息
/// </summary>
public class MusicData
{//背景音乐是否开启public bool isOpenBK;//音效是否开启public bool isOpenSound;//背景音乐音量public float bkValue;//音效音量public float soundValue;//加一个是否是第一次加载数据的标识public bool notFirst;
}
2.说明
(1)存储了 4 项核心配置:背景音乐开关(isOpenBK
)、音效开关(isOpenSound
)、背景音乐音量(bkValue
)、音效音量(soundValue
)
(2)notFirst
用于标记是否是首次进入游戏,便于初始化默认配置
3.游戏数据管理器:GameDataMgr
单例模式的游戏数据管理类,负责音乐数据的加载、更新和持久化存储。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 这个是游戏数据管理类 是一个单例模式对象
/// </summary>
public class GameDataMgr
{private static GameDataMgr instance = new GameDataMgr();public static GameDataMgr Instance { get => instance; }//音效数据对象public MusicData musicData;private GameDataMgr(){//初始化游戏数据musicData = PlayerPrefsDataMgr.Instance.LoadData(typeof(MusicData), "Music") as MusicData;//如果第一次进入游戏 没有音效数据 则初始化默认值if( !musicData.notFirst ){musicData.notFirst = true;musicData.isOpenBK = true;musicData.isOpenSound = true;musicData.bkValue = 1;musicData.soundValue = 1;PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");}}//提供一些API给外部 方便数据的改变存储//开启或者关闭背景音乐public void OpenOrCloseBKMusic(bool isOpen){musicData.isOpenBK = isOpen;//存储改变后的数据PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");}//开启或者关闭音效public void OpenOrCloseSound(bool isOpen){musicData.isOpenSound = isOpen;//存储改变后的数据PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");}//改变背景音乐大小public void ChangeBKValue(float value){musicData.bkValue = value;//存储改变后的数据PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");}//改变音效大小public void ChangeSoundValue(float value){musicData.soundValue = value;//存储改变后的数据PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");}
}
4.核心功能说明
(1)单例模式:通过私有构造函数和静态Instance
属性确保全局唯一实例
(2)数据初始化:
- 在构造函数中通过
PlayerPrefsDataMgr
加载本地存储的音乐配置 - 首次进入游戏时自动初始化默认配置(音乐音效开启,音量设为最大 1)
(3)数据操作 API:
- 提供了 4 个方法用于更新音乐配置(开关和音量调节)
- 每次数据变更后自动调用
SaveData
方法持久化存储
5.设置面板完善:SettingPanel
实现配置的实时更新和显示同步
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SettingPanel : BasePanel<SettingPanel>
{//1声明成员变量 关联控件public CustomGUISlider sliderMusic;public CustomGUISlider sliderSound;public CustomGUIToggle togMusic;public CustomGUIToggle togSound;public CustomGUIButton btnClose;// Start is called before the first frame updatevoid Start(){//2监听对应的事件 处理逻辑//处理音乐的变化sliderMusic.changeValue += (value) => GameDataMgr.Instance.ChangeBKValue(value);//处理音效的变化sliderSound.changeValue += (value) => GameDataMgr.Instance.ChangeSoundValue(value);//处理音乐开关togMusic.changeValue += (value) => GameDataMgr.Instance.OpenOrCloseBKMusic(value);//处理音效开关togSound.changeValue += (value) => GameDataMgr.Instance.OpenOrCloseSound(value);btnClose.clickEvent += () =>{//隐藏自己HideMe();//让开始面板重新显示出来BeginPanel.Instance.ShowMe();};HideMe();}//根据数据 更新面板public void UpdatePanelInfo(){//面板上的信息根据音效数据更新MusicData data = GameDataMgr.Instance.musicData;//设置面板内容sliderMusic.nowValue = data.bkValue;sliderSound.nowValue = data.soundValue;togMusic.isSel = data.isOpenBK;togSound.isSel = data.isOpenSound;}public override void ShowMe(){base.ShowMe();//每次显示面板时 同步更新面板内容UpdatePanelInfo();}
}
6.核心更新说明
(1)事件绑定优化:将滑块和开关的事件直接绑定到GameDataMgr
的 API,实现数据的实时更新
(2)面板数据同步:
- 新增
UpdatePanelInfo
方法,用于根据当前存储的音乐数据更新面板控件状态 - 重写
ShowMe
方法,确保每次打开面板时都能显示最新的配置信息
(3)交互逻辑:保持原有面板切换逻辑,关闭按钮点击后仍会隐藏设置面板并显示开始面板
六、排行榜的UI搭建与使用
1.开始面板的完善
public class BeginPanel : BasePanel<BeginPanel>
{......btnRank.clickEvent += () =>{//打开排行榜面板RankPanel.Instance.ShowMe();//避免穿透 隐藏自己HideMe();};
......}
}
排行榜按钮:点击后显示排行榜面板并隐藏自身
2.排行榜面板(RankPanel)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class RankPanel : BasePanel<RankPanel>
{//关联public的 控件对象public CustomGUIButton btnClose;//因为控件较多 拖的话 工作量太大了 我们直接偷懒 通过代码找private List<CustomGUILabel> labPM = new List<CustomGUILabel>();private List<CustomGUILabel> labName = new List<CustomGUILabel>();private List<CustomGUILabel> labScore = new List<CustomGUILabel>();private List<CustomGUILabel> labTime = new List<CustomGUILabel>();// Start is called before the first frame updatevoid Start(){for (int i = 1; i <= 10 ; i++){//小知识应用 找子对象的子对象 可以通过 斜杠来区分父子关系labPM.Add(this.transform.Find("PM/labPM" + i).GetComponent<CustomGUILabel>());labName.Add(this.transform.Find("Name/labName" + i).GetComponent<CustomGUILabel>());labScore.Add(this.transform.Find("Score/labScore" + i).GetComponent<CustomGUILabel>());labTime.Add(this.transform.Find("Time/labTime" + i).GetComponent<CustomGUILabel>());}//处理事件监听逻辑btnClose.clickEvent += () =>{HideMe();BeginPanel.Instance.ShowMe();};HideMe();}public override void ShowMe(){base.ShowMe();UpdatePanelInfo();}public void UpdatePanelInfo(){//处理根据排行榜数据 更新面板}
}
3.说明
(1)控件获取:通过代码查找方式获取 10 条排行榜数据所需的标签控件,分为排名(PM)、名称(Name)、分数(Score)和时间(Time)四个列表
(2)关闭按钮逻辑:点击后隐藏排行榜面板并显示开始面板
(3)面板显示:重写 ShowMe 方法,在显示面板时调用 UpdatePanelInfo 方法更新数据
(4)预留了 UpdatePanelInfo 方法,用于后续根据排行榜数据更新面板显示
七、排行榜数据系统与面板完善
1.单条排行榜数据:RankInfo类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 排行榜单条数据
/// </summary>
public class RankInfo
{public string name; // 玩家名称public int score; // 玩家分数public float time; // 游戏时间(秒)public RankInfo(){}public RankInfo(string name, int score, float time){this.name = name;this.score = score;this.time = time;}
}
该类定义了单条排行榜记录应包含的核心信息:玩家名称、分数和游戏时间,提供了默认构造函数和带参构造函数便于数据初始化。
2.排行榜列表容器:RankList类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 排行榜列表
/// </summary>
public class RankList
{public List<RankInfo> list; // 排行榜数据列表
}
简单的容器类,用于管理多条排行榜数据,便于进行序列化存储和批量处理。
3.游戏数据管理器完善扩展:GameDataMgr类
public class GameDataMgr
{......// 排行榜数据对象public RankList rankData;private GameDataMgr(){......// 初始化排行榜数据rankData = PlayerPrefsDataMgr.Instance.LoadData(typeof(RankList), "Rank") as RankList;}// 新增:添加排行榜数据并排序public void AddRankInfo(string name, int score, float time){rankData.list.Add(new RankInfo(name, score, time));// 按游戏时间升序排序(时间越短排名越前)rankData.list.Sort((a, b) => a.time < b.time ? -1 : 1);// 只保留前10条数据for (int i = rankData.list.Count - 1; i >= 10; i--){rankData.list.RemoveAt(i);}// 保存更新后的数据PlayerPrefsDataMgr.Instance.SaveData(rankData, "Rank");}......
}
4.核心扩展说明
(1)新增数据成员:添加rankData
用于存储排行榜数据列表
(2)初始化逻辑:在构造函数中通过PlayerPrefsDataMgr
加载本地存储的排行榜数据
(3)排行榜管理 API:
AddRankInfo
方法:添加新记录、按游戏时间排序、保留前 10 条数据并自动保存- 排序逻辑:使用 Lambda 表达式实现按游戏时间升序排序(时间越短排名越靠前)
- 数据限制:只保留排名前 10 的记录,超出部分从列表尾部移除
5.排行榜面板完善:RankPanel
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class RankPanel : BasePanel<RankPanel>
{// 关闭按钮public CustomGUIButton btnClose;// 排行榜显示控件列表(通过代码查找获取)private List<CustomGUILabel> labName = new List<CustomGUILabel>();private List<CustomGUILabel> labScore = new List<CustomGUILabel>();private List<CustomGUILabel> labTime = new List<CustomGUILabel>();void Start(){// 初始化控件列表(获取10条记录的显示控件)for (int i = 1; i <= 10 ; i++){labName.Add(this.transform.Find("Name/labName" + i).GetComponent<CustomGUILabel>());labScore.Add(this.transform.Find("Score/labScore" + i).GetComponent<CustomGUILabel>());labTime.Add(this.transform.Find("Time/labTime" + i).GetComponent<CustomGUILabel>());}// 关闭按钮事件btnClose.clickEvent += () =>{HideMe();BeginPanel.Instance.ShowMe();};// 测试代码(可选)// GameDataMgr.Instance.AddRankInfo("测试数据", 100, 8432);// 初始隐藏面板HideMe();}// 重写显示方法,显示时更新数据public override void ShowMe(){base.ShowMe();UpdatePanelInfo();}// 更新面板数据public void UpdatePanelInfo(){// 获取排行榜数据List<RankInfo> list = GameDataMgr.Instance.rankData.list;// 遍历数据更新UIfor (int i = 0; i < list.Count; i++){// 更新玩家名称labName[i].content.text = list[i].name;// 更新分数labScore[i].content.text = list[i].score.ToString();// 格式化时间(秒 -> 时:分:秒)int time = (int)list[i].time;labTime[i].content.text = "";// 处理小时if (time / 3600 > 0){labTime[i].content.text += time / 3600 + "时";}// 处理分钟if (time % 3600 / 60 > 0 || labTime[i].content.text != ""){labTime[i].content.text += time % 3600 / 60 + "分";}// 处理秒labTime[i].content.text += time % 60 + "秒";}}
}
6.功能说明
(1)控件初始化:通过代码查找方式获取 10 条记录所需的显示控件(名称、分数、时间),避免手动拖拽绑定的繁琐操作
(2)面板交互:关闭按钮点击后隐藏排行榜面板并显示开始面板,保持面板切换的一致性
(3)数据展示:
UpdatePanelInfo
方法:从GameDataMgr
获取排行榜数据并更新到 UI- 时间格式化:将秒数转换为 "时:分: 秒" 的易读格式,只显示有意义的时间单位
(4)显示逻辑:重写ShowMe
方法,确保每次打开面板时都能显示最新的排行榜数据
7.实现流程与原理
(1)数据流向:
- 新增记录 → 调用
GameDataMgr.AddRankInfo
→ 数据排序与限制 → 保存到本地 - 打开排行榜 → 调用
UpdatePanelInfo
→ 从GameDataMgr
获取数据 → 更新 UI 显示
(2)UI 结构要求:
- 排行榜面板需包含 Name、Score、Time 三个父节点
- 每个父节点下需有 10 个子节点(labName1 至 labName10 等),用于显示对应排名的信息
八、背景音乐管理系统
1.背景音乐管理类:BKMusic
该类负责背景音乐的实际播放控制,采用单例模式确保全局唯一的音乐管理实例。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class BKMusic : MonoBehaviour
{private static BKMusic instance;public static BKMusic Instance => instance;private AudioSource audioSource;// Start is called before the first frame updatevoid Awake(){instance = this;// 得到自己依附的游戏对象上挂载的音频源脚本audioSource = this.GetComponent<AudioSource>();// 初始化时根据数据设置音量和开关状态ChangeValue(GameDataMgr.Instance.musicData.bkValue);ChangeOpen(GameDataMgr.Instance.musicData.isOpenBK);}/// <summary>/// 改变背景音乐大小/// </summary>/// <param name="value"></param>public void ChangeValue(float value){audioSource.volume = value;}/// <summary>/// 开关背景音乐/// </summary>/// <param name="isOpen"></param>public void ChangeOpen(bool isOpen){// 如果开启就是不静音,关闭则静音audioSource.mute = !isOpen;}
}
2.核心功能说明
(1)单例模式实现:通过静态Instance
属性提供全局访问点,确保音乐控制的唯一性
(2)音频源获取:在Awake
方法中获取组件上的AudioSource
组件,用于实际的音频播放控制
(3)初始化配置:启动时自动从GameDataMgr
读取保存的音乐配置,设置初始音量和开关状态
(4)控制接口:
ChangeValue
:调整背景音乐音量ChangeOpen
:控制背景音乐开关(通过静音状态实现)
3.游戏数据管理器更新:GameDataMgr
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 游戏数据管理类(单例模式)
/// </summary>
public class GameDataMgr
{...... // 背景音乐开关控制(新增实时控制逻辑)public void OpenOrCloseBKMusic(bool isOpen){musicData.isOpenBK = isOpen;// 实时控制场景上的背景音乐开关BKMusic.Instance.ChangeOpen(isOpen);// 存储改变后的数据PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");}......// 背景音乐音量控制(新增实时控制逻辑)public void ChangeBKValue(float value){musicData.bkValue = value;// 实时控制场景上的背景音乐大小BKMusic.Instance.ChangeValue(value);// 存储改变后的数据PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");}
......}
4.核心更新说明
(1)背景音乐实时控制:
- 在
OpenOrCloseBKMusic
方法中新增BKMusic.Instance.ChangeOpen(isOpen)
调用,实现开关状态的实时生效 - 在
ChangeBKValue
方法中新增BKMusic.Instance.ChangeValue(value)
调用,实现音量的实时调整
(2)数据与播放同步:保持原有数据持久化逻辑,确保配置修改后既能立即生效,又能保存到本地
九、资源以及源代码
1.资源(切勿商用)
通过网盘分享的文件:资源.zip
链接: https://pan.baidu.com/s/1IOyXuw8z5YLATI9Bwwpn5Q?pwd=1111 提取码: 1111
--来自百度网盘超级会员v5的分享
2.源代码
因为只是UI且篇幅已经较长,所以项目以及源代码放在下篇(游戏场景篇)