Unity之MVC思想(通过普通方法和使用MVC思想完成同一个小案例:掌握MVC简单框架)

请添加图片描述

@作者 : SYFStrive

@博客首页 : 点击跳转HomePage

📌:个人社区(欢迎大佬们加入) 👉:社区链接🔗

💃:坚持锻炼💪

🔗:点击直接阅读文章
请添加图片描述
在这里插入图片描述
相关专栏

👉 Unirt~UI简单框架(🔥)


对MVC思想简单说明

  1. MVC思想就是一种让View(视图(UI界面))、Data(数据)之间分离,通过中介Controller(管理逻辑脚本)进行交互的一种框架思想,目的是为了减少代码的耦合性。

  2. MVC全名是Model View Controller,是模型(Model)👉 视图(View)👉 控制器(Controller)的缩写,是一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。

  3. M 👉 V 👉 C

    1、M(模型) 处理应用程序数据逻辑的部分 👉 通常模型对象负责在数据库中存取数据。
    2、V(视图) 是应用程序中处理数据显示的部分 👉 通常视图是依据模型数据创建的。
    3、C(控制器) 是应用程序中处理用户交互的部分 👉 通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据(管理相关逻辑)。

  4. 注意:1、Unity~MVC是一种非必须UI系统开发框架 2、主要用于开发游戏UI系统逻辑

  5. 优点:降低耦合性,方法修改,逻辑更清晰

  6. 缺点(1、有一定的性能消耗(如今的电脑配置基本可以忽略))

普通方法与MVC思想脚本进行对比

普通方法脚本如👇:

代码少、体积小、逻辑复杂😥

在这里插入图片描述
MVC思想脚本如👇:

脚本分开管理逻辑更加清晰😀

在这里插入图片描述

使用的UI预制体

在这里插入图片描述

最后效果

在这里插入图片描述

使用普通方法完成案例

图示如👇:

在这里插入图片描述

1、PlayerGradeManager

using UnityEngine;
using UnityEngine.UI;

public class PlayerGradeManager : MonoBehaviour
{
    //正常写法 通常四部走 获取对应组件 👉 添加事件 👉 更新信息 👉 动态显示
    
    //1、获取对应组件
    public Text txtLev;
    public Button playerBut;

    private static PlayerGradeManager playerGradeManageG;
    public static PlayerGradeManager PlayerGradeManageG { get => playerGradeManageG; }

    //2、添加事件
    private void Start()
    {
        playerBut.onClick.AddListener(() =>
        {
            //打开角色面板的逻辑
           PlayerInfoManager.ShowMe();
        });
    }

    //3、更新信息
    public void UpdateInfo()
    {
        //获取玩家数据 更新数据
        //获取数据方法 1、网格请求 2、json 3、xml 4、2进制 5、PlayerPrefs公共类

        //这里通过PlayerPrefs来获取本地存储的玩家信息  更新信息界面上
        txtLev.text = "等级:" + PlayerPrefs.GetInt("LevValue", 1).ToString();
    }

    //4、动态显示
    public static void ShowMe()
    {
        if (PlayerGradeManageG == null)
        {
            GameObject res = Resources.Load<GameObject>("UI/PlayerGrade");

            GameObject obj = Instantiate(res);

            //设置他的位置
            obj.transform.SetParent(GameObject.Find("Canvas").transform, false);

            //获取自身脚本
            playerGradeManageG = obj.GetComponent<PlayerGradeManager>();
        }

        //创建完后显示
        PlayerGradeManageG.gameObject.SetActive(true);

        //更新面板后同步数据
        PlayerGradeManageG.UpdateInfo();
    }
    public static void HideMe()
    {
        //方式一 :直接删除
        //if (playerGradeManager != null)
        //{
        //    Destroy(playerGradeManager.gameObject);
        //    playerGradeManager = null;
        //}

        //方式二 :隐藏
        PlayerGradeManageG.gameObject.SetActive(false);
    }
}

2、PlayerInfoManager

using UnityEngine;
using UnityEngine.UI;

public class PlayerInfoManager : MonoBehaviour
{
   //正常写法 通常四部走
   
   //1、获取对应组件
   public Text playerAttack;
   public Text hp;
   public Text defense;
   public Text txtLev;
   public Button upgrade;
   public Button hideBag;

   private static PlayerInfoManager playerInfo;

   //2、添加事件
   private void Start()
   {
       upgrade.onClick.AddListener(() =>
       {
           Debug.Log("sasd");
           //升级相关逻辑
           UpLev();

       });

       hideBag.onClick.AddListener(() =>
       {
           //隐藏面板
           HideMe();
       });
   }
   //3、更新信息
   private void UpdateInfo()
   {
       //获取玩家数据 更新数据
       //获取数据方法 1、网格请求 2、json 3、xml 4、2进制 5、PlayerPrefs公共类

       //这里通过PlayerPrefs来获取本地存储的玩家信息  更新信息界面上
       txtLev.text = PlayerPrefs.GetInt("LevValue",1).ToString();
       playerAttack.text = PlayerPrefs.GetInt("AttackValue", 888).ToString();
       hp.text = PlayerPrefs.GetInt("HpValue", 888).ToString();
       defense.text = PlayerPrefs.GetInt("DefenseValue", 888).ToString();
   }
   //4、动态显示
   public static void ShowMe()
   {
       if (playerInfo == null)
       {
           GameObject res = Resources.Load<GameObject>("UI/PlayerInfo");

           GameObject obj = Instantiate(res);

           //设置他的位置
           obj.transform.SetParent(GameObject.Find("Canvas").transform, false);

           //获取自身脚本
           playerInfo = obj.GetComponent<PlayerInfoManager>();
       }

       //创建完后显示
       playerInfo.gameObject.SetActive(true);

       //更新面板后同步数据
       playerInfo.UpdateInfo();
   }
   public static void HideMe()
   {
       //方式一 :直接删除
       //if (playerGradeManager != null)
       //{
       //    Destroy(playerGradeManager.gameObject);
       //    playerGradeManager = null;
       //}

       //方式二 :隐藏
       playerInfo.gameObject.SetActive(false);
   }

   //升级相关逻辑
   private void UpLev()
   {
       //获取数据
       int LevValueInt = PlayerPrefs.GetInt("LevValue", 1);
       int AttackValueInt= PlayerPrefs.GetInt("AttackValue", 888);
       int HpValueInt = PlayerPrefs.GetInt("HpValue", 888);
       int DefenseValueInt = PlayerPrefs.GetInt("DefenseValue", 888);
       //更新磁盘里面的数据
       int add = 50;
       LevValueInt += add;
       AttackValueInt += add;
       HpValueInt += add;
       DefenseValueInt += add;

       PlayerPrefs.SetInt("LevValue", LevValueInt);
       PlayerPrefs.SetInt("AttackValue", AttackValueInt);
       PlayerPrefs.SetInt("HpValue", HpValueInt);
       PlayerPrefs.SetInt("DefenseValue", DefenseValueInt);

       //同步面板数据
       UpdateInfo();

       //同步PlayerGradeManager~UI界面的数据
       PlayerGradeManager.PlayerGradeManageG.UpdateInfo();
   }
}

3、UI_Evenemt (UI事件)

using UnityEngine;

public class UI_Evenemt : MonoBehaviour
{
    private bool isShowBag;

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.B))
        {
            //显示隐藏面板
            isShowBag = !isShowBag;
            if (isShowBag)
                PlayerGradeManager.ShowMe();
            else
                PlayerGradeManager.HideMe();
        }
    }
}

使用MVC思想完成案例

图示如👇:

在这里插入图片描述

1、Controller

PlayerGradeController

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

//MVC中的C 👉 1、Controller负责相关逻辑 👉 2、界面事件监听等 处理对应的业务逻辑 👉 3、界面更新
public class PlayerGradeController : MonoBehaviour
{
    //在Controller获取View 简单理解?? C控制V
    private PlayerGradeView playerGradeView;

    private static PlayerGradeController playerGradeControllerC=null;

    public static PlayerGradeController PlayerGradeControllerC { get => playerGradeControllerC;}


    private void Start()
    {
        //获取View脚本 👉 第一次更新界面  👉 监听事件处理相关逻辑

        //获取View脚本
        playerGradeView = GetComponent<PlayerGradeView>();
        //更新界面
        playerGradeView.UpdateInfo(ModeData.Instance);
        //事件监听
        playerGradeView.playerBut.onClick.AddListener(() =>
        {
            PlayerInfoController.ShowMe();
        });
        //添加委托事件
        ModeData.Instance.AddEvent(UpdateInFo);
    }


    //见面的显示与隐藏
    public static void ShowMe()
    {
        if (playerGradeControllerC == null)
        {
            //实例化UI对象
            GameObject res = Resources.Load<GameObject>("UI/PlayerGradeS");
            GameObject obj = Instantiate(res);
            //设置其位置到Canvas
            obj.transform.SetParent(GameObject.Find("Canvas").transform,false);
            //判断是否实例过
            playerGradeControllerC = obj.GetComponent<PlayerGradeController>();
        }

        playerGradeControllerC.gameObject.SetActive(true);
    } 
    public static void HideMe()
    {
        //方式一 :直接删除
        //if (playerGradeManager != null)
        //{
        //    Destroy(playerGradeManager.gameObject);
        //    playerGradeManager = null;
        //}

        //方式二 :隐藏
        if(playerGradeControllerC != null)
            playerGradeControllerC.gameObject.SetActive(false);
    }

    //更新同步数据
    private void UpdateInFo(ModeData function)
    {
        playerGradeView.UpdateInfo(function);
    }
}

PlayerInfoController

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

//MVC中的C 👉 1、Controller负责相关逻辑 👉 2、界面事件监听等 处理对应的业务逻辑  👉 3、界面更新……
public class PlayerInfoController : MonoBehaviour
{
    //在Controller获取View 简单理解 👉 C控制V
    private PlayerInfoView playerInfoView;

    private static PlayerInfoController playerInfoControllerC=null;

    public static PlayerInfoController PlayerInfoControllerC { get => playerInfoControllerC; }


    private void Start()
    {
        //获取View脚本 👉  第一次更新界面  👉 监听事件处理相关逻辑

        //获取View脚本
        playerInfoView = GetComponent<PlayerInfoView>();
        //更新界面
        playerInfoView.UpdateInfo(ModeData.Instance);
        //添加委托事件
        ModeData.Instance.AddEvent(UpdateInFo);
        //事件监听
        playerInfoView.upgrade.onClick.AddListener(() =>
        {
            ModeData.Instance.UpLev();
        });
        playerInfoView.hideBag.onClick.AddListener(() =>
        {
            HideMe();
        });
    }


    //见面的显示与隐藏
    public static void ShowMe()
    {
        if (playerInfoControllerC == null)
        {
            //实例化UI对象
            GameObject res = Resources.Load<GameObject>("UI/PlayerInfoS");
            GameObject obj = Instantiate(res);
            //设置其位置到Canvas
            obj.transform.SetParent(GameObject.Find("Canvas").transform, false);
            //判断是否实例过
            playerInfoControllerC = obj.GetComponent<PlayerInfoController>();
        }

        playerInfoControllerC.gameObject.SetActive(true);
    }

    private static void HideMe()
    {
        //方式一 :直接删除
        //if (playerGradeManager != null)
        //{
        //    Destroy(playerGradeManager.gameObject);
        //    playerGradeManager = null;
        //}

        //方式二 :隐藏
        if (playerInfoControllerC != null)
            playerInfoControllerC.gameObject.SetActive(false);
    }

    //更新同步数据
    private void UpdateInFo(ModeData function)
    {
        playerInfoView.UpdateInfo(function);
    }
}

2、ModelData

ModeData

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

//MVC中的M 👉 储存数据
public class ModeData
{
    //MVC 👉 M一般流程 如👇:
    //1、数据内容 ?? 2、数据相关操作&&初始化 ……?? 3、更新数据 ?? 4、储存数据 ……

    //1、数据内容
    private int playerLve;

    private int lev;
    private int attackValue;
    private int hp;
    private int defense;

    public int PlayerLve { get => playerLve; }

    public int Lev { get => lev;}
    public int AttackValue { get => attackValue;}
    public int Hp { get => hp;}
    public int Defense { get => defense;}

    //使用单例用于外部调用 (M一般情况:自己是个静态单例 或者 存在一个单例模式对象中)
    private static ModeData instance=null;

    public static ModeData Instance {
        get
        {
            if (instance == null)
            {
                instance = new ModeData();
                instance.Init();
            }
             return instance;
        }
    }

    //使用MVC思想不能从M去调用 其他的事件…… (使用事件)
    private event UnityAction<ModeData> updateDataEvent;


    //2、数据相关操作 (初始化……)
    public void Init()
    {
        //初始化数据
        playerLve = PlayerPrefs.GetInt("LevValue", 1);

        lev = PlayerPrefs.GetInt("LevValue", 1);
        attackValue = PlayerPrefs.GetInt("AttackValue", 888);
        hp = PlayerPrefs.GetInt("HpValue", 888);
        defense = PlayerPrefs.GetInt("DefenseValue", 888);
    }

    //3、更新本地数据
    public void UpLev()
    {
        int add = 50;

        playerLve += add;

        lev += add;
        attackValue += add;
        hp += add;
        defense += add;

        Save();
    }

    //4、储存数据
    public void Save()
    {
        PlayerPrefs.SetInt("LevValue", lev);

        PlayerPrefs.SetInt("LevValue", lev);
        PlayerPrefs.SetInt("AttackValue", attackValue);
        PlayerPrefs.SetInt("HpValue", hp);
        PlayerPrefs.SetInt("DefenseValue", defense);

        UpdateInFo();
    }

    //添加事件
    public void AddEvent(UnityAction<ModeData> function)
    {
        updateDataEvent += function;
    }
    //移除事件
    public void RemoveEvent(UnityAction<ModeData> function)
    {
        updateDataEvent -= function;
    }

    //使用事件通知外部更新数据
    private void UpdateInFo()
    {
        //第一种写法 👇
        //if (updateDataEvent != null)
        //{
        //    updateDataEvent(this);
        //}

        //第二种写法  👇
        updateDataEvent?.Invoke(this);
    }

}

3、View

PlayerGradeView

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

//MVC中的V 👉 1、完成控件的查找  👉 2、提供UI更新的方法给外部
public class PlayerGradeView : MonoBehaviour
{
    //1、完成控件的查找
    public Text txtLev;
    public Button playerBut;


    //2、提供UI更新的方法给外部
    public void UpdateInfo(ModeData modeData)
    {
        txtLev.text = "等级:"+modeData.PlayerLve.ToString();
    }
}

PlayerInfoView

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

//MVC中的V 👉 1、完成控件的查找 👉 2、提供UI更新的方法给外部……
public class PlayerInfoView : MonoBehaviour
{
    //1、完成控件的查找
    public Text txtLev;
    public Text playerAttack;
    public Text hp;
    public Text defense;
    public Button upgrade;
    public Button hideBag;


    //2、提供UI更新的方法给外部
    public void UpdateInfo(ModeData modeData)
    {
        txtLev.text = modeData.Lev.ToString();
        playerAttack.text = modeData.AttackValue.ToString();
        hp.text = modeData.Hp.ToString();
        defense.text = modeData.Defense.ToString();
    }
}

最后

在这里插入图片描述

本文到这里就结束了,大佬们的支持是我们更新的最大动力,希望这篇文章能帮到大家💪

在这里插入图片描述

下篇文章再见ヾ( ̄▽ ̄)ByeBye

在这里插入图片描述

  • 25
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 21
    评论
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SYFStrive

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值