【unity之IMGUI实践】单例模式管理数据存储【二】

news2024/11/20 4:40:50

在这里插入图片描述


👨‍💻个人主页:@元宇宙-秩沅

👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!

👨‍💻 本文由 秩沅 原创

👨‍💻 收录于专栏unityUI专题篇
在这里插入图片描述


单例模式管理面板对象


文章目录

    • 单例模式管理面板对象
    • 🎶前言
    • 🎶(==A==)常用关键API
    • 🎶(==B==)需求分析
    • 🎶(==C==)逻辑封装——游戏音乐数据存储
      • 😶‍🌫️:步骤实现
        • 实现音乐数据的同步更新——最终代码
    • 🎶(==D==)逻辑封装——游戏排行榜数据存储
      • 😶‍🌫️:**步骤实现**
        • 总UML图
    • 👌结论:


🎶前言


🅰️


🎶(A常用关键API


在这里插入图片描述
在这里插入图片描述


🎶(B需求分析


在这里插入图片描述


🎶(C逻辑封装——游戏音乐数据存储


在这里插入图片描述
在这里插入图片描述


😶‍🌫️:步骤实现

1.首先将音乐数据封装在类中,不采用单例模式
2. 而后封装一个游戏数据类为单例模式:功能:利用Playerfabs进行数据存储音乐数据
3.读取存盘中的数据更新游戏数据


1.首先将音乐数据封装在类中,不采用单例模式

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________脚本名:   音乐相关数据存储类      
//___________功能:    记录音乐相关的数据 
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class MusicData 
{
    
    //记录音乐,音效的开关状态和拖动条
    public bool  musicSwitch;
    public bool  soundSwitch;
    public float musicRoll;
    public float soundRoll;
    public bool isFirst;
}

2. 而后封装一个游戏数据类为单例模式:功能:利用Playerfabs进行数据存储音乐数据

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________脚本名:   游戏数据类   
//___________功能:    记录游戏的数据并用PlayerFabs存储
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------

public class GameData         
{
    static private GameData dataContorl = new GameData ();
    static public  GameData DataContorl => dataContorl ;
    public MusicData musicData ;

    private GameData()
    {
        musicData = new MusicData();
        musicData = PlayerfabsClass.Chats.GetDataMess(typeof(MusicData), "Music") as MusicData ;
        if ( !musicData.isFirst ) //如果是第一次进入游戏
        {
            musicData.musicSwitch = true;
            musicData.soundSwitch = true;
            musicData.musicRoll = 0.5f;
            musicData.soundRoll = 0.5f;
            PlayerfabsClass.Chats.SaveDataMess(musicData, "Music");   //设置为自定义的默认值后进行存储             
        }
    }
    
}

3.读取存盘中的数据更新游戏数据

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:       ______________
//___________功能:  设置面板功能
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class SetPlane : BeginFather<SetPlane>
{
  //将功能控件拖拽对应的成员变量中
    public Button closeButt;
    public Slider sliderMusic;
    public Slider sliderSound;
    public ToggleM toggleMusic;
    public ToggleM toggleSound;

    private float toggle1;
    private float toggle2;

    private void Start()
    {
        
        //按钮中事件的添加
        closeButt.triggerEvent += () => {
            this.gameObject.SetActive(false);
            BeginPlane.SingleInstance.Show();
        };
        //滑条中事件的添加
   
        sliderMusic.triggerEvent += (value) =>
        {
            
        };
        sliderSound.triggerEvent += (value) =>
        {

        };
        //多选框中事件的添加

        toggleMusic.triggerEvent += (value) =>
        {

        };
        toggleSound .triggerEvent += (value) =>
        {

        };
        this.Hidden();
    }

    private void MusicDataUpdate()
    {
        MusicData data = GameData.DataContorl.musicData;
        sliderMusic.NowValue = data.musicRoll;
        sliderSound.NowValue = data.soundRoll;
        toggleMusic.IsSwitch = data.musicSwitch;
        toggleSound.IsSwitch = data.soundSwitch;
    }

    public override void Show()
    {
        base.Show();  //保留父类的封装逻辑
        MusicDataUpdate();
    }
}


实现音乐数据的同步更新——最终代码


目的: 将游戏游戏数据保存至硬盘,下次开启游戏实现数据同步

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________脚本名:   游戏数据类   
//___________功能:    记录游戏的数据并用PlayerFabs存储
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------

public class GameData         
{
    static private GameData dataContorl = new GameData ();
    static public  GameData DataContorl => dataContorl ;
    public MusicData musicData ;

    private GameData()
    {
       
        musicData = PlayerPrefsDataMgr.Instance.LoadData(typeof(MusicData), "Music") as MusicData ;

        if ( !musicData.isFirst ) //如果是第一次进入游戏(表示注册表中第一次存该类型数据时)
        {
            musicData.isFirst = true;
            musicData.musicSwitch = true;
            musicData.soundSwitch = true;
            musicData.musicRoll = 1f;
            musicData.soundRoll = 1f;
            PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");                
        }
    }
    
    //音乐开关数据的更新存储

    public void ChangeMusicS( bool value)
    {
        musicData.musicSwitch = value;
        PlayerPrefsDataMgr.Instance.SaveData(musicData,"Music");
    }

    //音效开关数据的更新存储

    public void ChangeSoundS(bool value)
    {
        musicData.soundSwitch  = value;
        PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");
    }

    //音乐滑条数据的更新存储

    public void ChangeMusicR(float value)
    {
        musicData.musicRoll  = value;
        PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");
    }

    //音效滑条数据的更新存储

    public void ChangeSoundR(float value)
    {
        musicData.soundRoll  = value;
        PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");
    }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:       ______________
//___________功能:  设置面板功能
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class SetPlane : BeginFather<SetPlane>
{
  //将功能控件拖拽对应的成员变量中
    public Button closeButt;
    public Slider sliderMusic;
    public Slider sliderSound;
    public ToggleM toggleMusic;
    public ToggleM toggleSound;

    private float toggle1;
    private float toggle2;
    private MusicData musicData;

    private void Start()
    {
        
        //按钮中事件的添加
        closeButt.triggerEvent += () => {
            Hidden();
            BeginPlane.SingleInstance.Show();
        };
        //多选框中事件的添加

        toggleMusic.triggerEvent += (value) => GameData.DataContorl.ChangeMusicS(value);

        toggleSound.triggerEvent += (value) => GameData.DataContorl.ChangeSoundS(value);
        //滑条中事件的添加

        sliderMusic.triggerEvent += (value) => GameData.DataContorl.ChangeMusicR(value);

        sliderSound.triggerEvent += (value) => GameData.DataContorl.ChangeSoundR(value);
      
        Hidden();
    }


    private void MusicDataUpdate() //将已存盘的数据读取后更新
    {
        MusicData data = GameData.DataContorl.musicData;

        toggleMusic.IsSwitch = data.musicSwitch;
        toggleSound.IsSwitch = data.soundSwitch;
        sliderMusic.NowValue = data.musicRoll;
        sliderSound.NowValue = data.soundRoll;
    
    }

    
    public override void Show()
    {
        base.Show();        //保留父类的封装逻辑
        MusicDataUpdate();  //在展示时更新
    }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
//-------------------------------------
//—————————————————————————————————————
//___________项目:       ______________
//___________功能: 开始面板类
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class BeginPlane : BeginFather<BeginPlane>
{
    // 获取开始面板中的各个按钮控件

    public Button but1;
    public Button but2;
    public Button but3;
    public Button but4;
   
    private void Start()
    {
        but1.triggerEvent += () => { SceneManager.LoadScene("Start"); };                 //点击“开始游戏”
        but2.triggerEvent += () => { Hidden(); SetPlane.SingleInstance.Show();   };      //点击“游戏设置”
        but3.triggerEvent += () => { Application.Quit(); };                              //点击“退出游戏”
        but4.triggerEvent += () => { Hidden();  };                                       //点击“排行榜”
    }


}


🎶(D逻辑封装——游戏排行榜数据存储


界面设计

在这里插入图片描述

  • 效果演示:在这里插入图片描述

😶‍🌫️:步骤实现

  • 1.封装排行榜数据类(无参构造做new ,有参构造做一键赋值)

  • 2.以数据管理类为载体进行更新API封装——只存储排行榜中的数据到盘(注册表)中

  • 3.封装排行榜面板类进行实时显示


在这里插入图片描述-----在这里插入图片描述

封装排行榜数据类(无参构造做new ,有参构造做一键赋值)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:   
//___________功能: 排行榜数据的载体    
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class RankData
{ 
    public string name;
    public int score;
    public int time;
    public RankData() //用来new
    {

    }
    public RankData(string name, int score, int time ) //用来一键赋值
    {
        this.name = name ;
        this.score = score ;
        this.time = time;
    }
}

在这里插入图片描述 ----------------------在这里插入图片描述
以数据管理类为载体进行更新API封装

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________脚本名:   游戏数据管理类   
//___________功能:    记录和更新游戏的数据并用PlayerFabs存储
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------

public class GameData         
{
    static private GameData dataContorl = new GameData ();
    static public  GameData DataContorl => dataContorl ;
    public MusicData musicData ;
    public List<RankData> rankTopData;//固定承载前六名的数据信息

    private GameData()
    {
       
        //初始化读取音乐数据
        musicData = PlayerPrefsDataMgr.Instance.LoadData(typeof(MusicData), "Music") as MusicData ;
        //初始化读取排行榜数据
        rankTopData = PlayerPrefsDataMgr.Instance.LoadData(typeof(List<RankData>), "Rank") as List<RankData>;

        if ( !musicData.isFirst ) //如果是第一次进入游戏(表示注册表中第一次存该类型数据时)
        {
            musicData.isFirst = true;
            musicData.musicSwitch = true;
            musicData.soundSwitch = true;
            musicData.musicRoll = 1f;
            musicData.soundRoll = 1f;
            PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");                
        }
      
          }       
    //------------------------排行榜数据的更新封装-------------------------------

        
    //在排行榜中添加数据

    public void SaveRankData(string name, int score, int time)
    {
        rankTopData.Add(new RankData(name, score, time));
        Debug.Log(rankTopData);
        rankTopData.Sort((a, b) => { return a.score > b.score ? -1 : 1; }); //添加排序规则

        //但list大于6时
        for (int i = rankTopData.Count - 1 ; i > 5; i--)
        {
            rankTopData.RemoveAt(i); //删除
        }
        
        PlayerPrefsDataMgr.Instance.SaveData(rankTopData, "Rank" );
    }


    //------------------------音乐数据的更新封装------------------------------

    //音乐开关数据的更新存储

    public void ChangeMusicS( bool value)
    {
        musicData.musicSwitch = value;
        PlayerPrefsDataMgr.Instance.SaveData(musicData,"Music");
    }

    //音效开关数据的更新存储

    public void ChangeSoundS(bool value)
    {
        musicData.soundSwitch  = value;
        PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");
    }

    //音乐滑条数据的更新存储

    public void ChangeMusicR(float value)
    {
        musicData.musicRoll  = value;
        PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");
    }

    //音效滑条数据的更新存储

    public void ChangeSoundR(float value)
    {
        musicData.soundRoll  = value;
        PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music");
    }
}


在这里插入图片描述-----------在这里插入图片描述
3.封装排行榜面板类进行实时显示

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

//-------------------------------------
//—————————————————————————————————————
//___________脚本名:  排行榜面板
//___________功能:   掌控排行榜面板相关控件
//___________创建者: 秩沅_______________
//_____________________________________
//-------------------------------------


public class RankPlane : BeginFather<RankPlane >
{

    public Button closeButton;

    //采用列表的方式进行排行数据的暂时存储

    private List<Label> RK_Name = new List<Label>();
    private List<Label> RK_Score = new List<Label>();
    private List<Label> RK_Time = new List<Label>();
  
    private void Start()
    {
        //通过API获取排行榜中的标签
        for (int i = 1; i <= 6; i++)
        {        
            RK_Name.Add(this.transform.Find("RKName/player" + i ).GetComponent<Label>());
            RK_Score.Add(this.transform.Find("RKScore/Score" + i ).GetComponent<Label>());
            RK_Time.Add(this.transform.Find("RKTime/time" + i ).GetComponent<Label>());       
        } 

        //为按钮中的事件添加方法
        closeButton .triggerEvent += ()=>{
            Hidden(); BeginPlane.SingleInstance.Show();
        };
        Hidden();    
    }

    public override void Show()
    {
        base.Show();
        ShowRankData();
    }

    public void ShowRankData()  //读盘排行榜数据并显示
    {
        GameData.DataContorl .SaveRankData("nibb", 100, 342);
        List<RankData> data = GameData.DataContorl.rankTopData;
        
        for (int i = 0; i < data.Count; i++)
        {
            string showTime = "";
            int hour, min, second;
            print(data[i].name);
            RK_Name[i].ContorlContent.text = data[i].name;
            RK_Score[i].ContorlContent.text = data[i].score.ToString();
            RK_Time[i].ContorlContent.text = "";
            //时间格式转化
            hour = data[i].time / 3600;
            min = data[i].time / 60 % 60;
            second = data[i].time % 60;
            showTime = $"{hour}小时{min}分钟{second}秒";

            RK_Time[i].ContorlContent.text = showTime;
        }
    }
}

总UML图

在这里插入图片描述


在这里插入图片描述


👌结论:

1.进行模块化处理,数据管理就是数据管理,面板显示就是面板显示,各司其职,员工不得乱工作
2.抽象行为,分配行为,你就是掌控者


相关文章


⭐【2023unity游戏制作-mango的冒险】-6.关卡设计

⭐【2023unity游戏制作-mango的冒险】-5.攻击系统的简单实现

⭐【2023unity游戏制作-mango的冒险】-4.场景二的镜头和法球特效跟随

⭐【2023unity游戏制作-mango的冒险】-3.基础动作和动画API实现

⭐【2023unity游戏制作-mango的冒险】-2.始画面API制作

⭐【2023unity游戏制作-mango的冒险】-1.场景搭建

⭐“狂飙”游戏制作—游戏分类图鉴(网易游学)

⭐本站最全-unity常用API大全(万字详解),不信你不收藏



你们的点赞👍 收藏⭐ 留言📝 关注✅是我持续创作,输出优质内容的最大动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/755816.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FocusState, SubmitTextField 的使用

1. FocusState 输入文本添加焦点状态 1.1 实现 /// 输入文本焦点状态 struct FocusStateBootcamp: View {// 使用枚举enum OnboardingFields: Hashable{case usernamecase password}//FocusState private var usernameInFocus: BoolState private var username: String "…

两分钟python发个邮件

python简单发个邮件 直接上代码测试 之前spring boot简单发送发送个邮件大约5min&#xff0c;ennn这个python发个邮件两三分钟吧 直接上代码 import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMETextclass MailTest(object):def…

Flink 在新能源场站运维的应用

摘要&#xff1a;本文整理自中南电力设计院工程师、注册测绘师姚远&#xff0c;在 Flink Forward Asia 2022 行业案例专场的分享。本篇内容主要分为四个部分&#xff1a; 1. 建设背景 2. 技术架构 3. 应用落地 4. 后续及其他 Tips&#xff1a;点击「阅读原文」免费领取 5000CU*…

Vue localhost 从 http 307 到 https

Vue localhost 从 http 307 到 https HTTP 307 与 HSTS HTTP 307中间人攻击HSTS - HTTP Strict Transport Security 如何解决问题 Vue localhost 从 http 307 到 https 一个 Vue2 项目之前本地都是通过 HTTP 的 localhost 访问(如下) 后来突然无法访问了, 提示的错误内容是 E…

静电接地桩的设计和施工

静电接地桩是用于将静电荷引导到地下的装置&#xff0c;以确保工作环境。以下是一般静电接地桩设计的一些建议和步骤&#xff1a; 1. 选择合适的位置&#xff1a;静电接地桩应该位于静电产生源附近&#xff0c;并接近地面。可以选择在室内或室外&#xff0c;但要确保容易维护和…

web中引入live2d的moc3模型

文章目录 前言下载官方sdk文件使用ide编译项目&#xff08;vsCode&#xff09;项目初始化使用vsCode项目树介绍使用live server运行index页面 演示导入自己的模型并显示modelDir文件resources文件夾案例模型修改modelDir然後重新打包項目運行 前言 先跟着官方sdk调试一遍&…

14.live555mediaserver-play请求与响应

live555工程代码路径 live555工程在我的gitee下&#xff08;doc下有思维导图、drawio图&#xff09;&#xff1a; live555 https://gitee.com/lure_ai/live555/tree/master 章节目录链接 0.前言——章节目录链接与为何要写这个&#xff1f; https://blog.csdn.net/yhb1206/art…

基于C/S架构工作原理序号工作步骤和理论的区别

基于C/S架构工作原理序号工作步骤和理论的区别 SSH 概念 对称加密linux 系统加密&#xff0c;就是加密和揭秘都是使用同一套密钥。 非对称加密有两个密钥&#xff1a;“私钥”和“公钥”。私钥加密后的密文&#xff0c;只能通过对应的公钥进行揭秘。而通过私钥推理出公钥的…

深入解析浏览器Cookie(图文码教学)

深入解析浏览器Cookie 前言一、什么是 Cookie?二、Cookie的特点二、如何创建 Cookie&#xff1f;三、服务器如何获取 Cookie四、Cookie 值的修改4.1 方案一4.2 方案二 五、浏览器查看 Cookie六、Cookie 生命控制七、Cookie 有效路径 Path 的设置八、案例&#xff1a;Cookie 练…

183_Power BI 折线图之平滑线性类型

183_Power BI 折线图之平滑线性类型 一、背景 曾几何时&#xff0c;为了在 Power BI 让折线图显示出平滑曲线&#xff0c;各路大佬是尽显神通。如今时间来到 2023 年 7 月&#xff0c;刚刚更新的 Power BI 已经支持折线图的平滑曲线。让我们来看看最终效果。 同时&#xff0c…

【SpringBoot3】--04.核心原理

文章目录 SpringBoot3-核心原理1.事件和监听器1.1生命周期监听1.1.1 监听器-SpringApplicationRunListener1.1.2生命周期全过程 1.2事件触发时机1.2.1各种回调监听器1.2.2完整触发流程 1.3SpringBoot事件驱动开发 2.自动配置原理2.1入门理解2.1.1自动配置流程2.1.2SPI机制2.1.3…

apache ranger

简介&#xff1a; ranger 是一个用于启用、监控和管理跨hadoop平台的全面的数据安全框架。 ranger的愿景是在hadoop系统中提供全面的安全管理。随着yarn的出现&#xff0c;hadoop 平台能够支持真正的数据糊架构。企业能够在多租户环境中运行多个任务负载。hadoop 数据安全需要…

面向对象编程/原型及原型链

一.面向对象 (1)对象是什么?为什么要面向对象? 通过对代码的抽象,进而描述单个种类物体的方式. (2)特点:面向对象-逻辑上迁移更加灵活,代码的复用性更高,高度的模块化. (3)对象的理解 1.对象是对于单个物体的简单抽象; 2.对象是容器,封装了属性和方法 **属性:对象状态…

Python官方文档中Availability: not Emscripten, not WASI是什么意思?

在我们阅读Python官方文档中&#xff0c;当某个模块或特性的文档中写着 "Availability: not Emscripten, not WASI" 时&#xff0c;它表示该模块或特性在 Emscripten 和 WASI 环境中不可用。 Emscripten 是一个工具链&#xff0c;用于将C和C代码编译为WebAssembly&am…

【Python从入门到进阶】28、xpath的安装以及使用

接上篇《27、Handler处理器使用及代理和Cookie登录实现》 上一篇我们讲解了urllib中Handler处理器的基本使用&#xff0c;以及实现代理访问和Cookie的登录。本篇我们来讲解HTML文档解析中的核心插件xpath的安装及使用。 一、xpath介绍 XPath是由W3C&#xff08;World Wide We…

kotlin中使用Room数据库(包含升降级崩溃处理)

目录 1.导入依赖库 2.数据实体类 3.数据访问对象 (DAO) 4.数据库类 5.调用DAO里面的“增、删、改、查”方法 6.数据库升降级处理 升级&#xff08;保存数据库历史数据&#xff09;&#xff1a; 升级&#xff08;不保存数据库历史数据&#xff09;&#xff1a; 降级&…

剑指 offer 数学算法题:数值的整数次方

题目描述&#xff1a; 实现 pow(x, n) &#xff0c;即计算 x 的 n 次幂函数&#xff08;即&#xff0c;xn&#xff09;。不得使用库函数&#xff0c;同时不需要考虑大数问题。 分析&#xff1a; 直接计算法&#xff0c;通过判断 n 的正负&#xff0c;若为负数&#xff0c; x 即…

无法加载文件\venv\Scripts\Activate.ps1,因为在此系统上禁止运行脚本

一、问题发生 运行环境Windows 10、python 3.11.1、IDE VScode 当然你可能使用了其他IDE&#xff0c;例如pycharm等&#xff0c;不过没有关系解决问题的方法都是一致的。 报错信息如下图所示&#xff1a; actvivate.ps1这个脚本文件是用来激活python虚拟环境的。 其实&…

LabVIEW开发图像采集和图像处理程序

LabVIEW开发图像采集和图像处理程序 扫描电子显微镜&#xff08;SEM&#xff09;是一种功能强大的工具&#xff0c;广泛用于高分辨率的生物和半导体样品检测。然而&#xff0c;对于大面积或3D成像&#xff0c;SEM成像是一个耗时的过程。MBSEM旨在通过同时扫描多个像素来减少采…

spring5源码篇(10)——spring-aop代理过程

spring-framework 版本&#xff1a;v5.3.19 文章目录 1、ProxyFactory1.1、createAopProxy() 创建AopProxy1.2、getProxy() 创建代理对象1.3、JdkDynamicAopProxy#invoke 代理逻辑1.3.1、advised.getInterceptorsAndDynamicInterceptionAdvice() 匹配添加的advisor并转化成所需…