Unity MVC框架之见解

  • MVC框架认识
  • 构架图
  • 案例
  • 无框架,普通逻辑代码脚本
  • 主UI脚本
  • 角色UI脚本
  • 摄像机显示脚本
  • 脚本的放置
  • MVC框架的运用
  • Model脚本
  • View脚本
  • 主界面的View脚本
  • 角色View脚本
  • Controller脚本
  • 主界面的Controller脚本
  • 角色Controller脚本
  • 控制主界面的显示脚本
  • 脚本控件物体的连接
  • 总结


MVC框架认识

MVC框架本不是用于在游戏行业产生的框架,但是其编程思想对游戏开发的影响也很大。
M: model,是模型的意思,可是模型是为何物?是我们游戏中所要操作的人物模型等等。其主要就是存储数据的一个物体。我们所见到的的软件等等,都是本身去操作一条条的数据去运行。所以该M脚本的主要内容就是操作数据。数据有什么操作呢???数据无外乎有两个作用,更新和保存
V: View,是视图的的意思。该部分应该很好理解,那就是控制UI的,控制一些什么按钮什么的。用该部分的脚本去实现和M数据的显示。
C: control,管理器的意思。该部分的脚本主要是控制模型和视图的交互作用。给视图中的UI注册事件,模型的实时更新保存。(也就是调用M和V中的方法)

构架图

unity mvc ui框架 unity mvc框架工作原理_unity mvc ui框架


人们通过点击View的ui按钮进行给控制器通知,通过控制器给ui注册是事件运行来操作model的数据。然后数据开始响应控制器的信息来进行数据的更新和保存,并反馈给控制器,控制器再进行响应通知view面板开始对数据的变化显示等等。

案例

我们分为两个模块来进行展示。一种是使用了框架,一种是没有使用框架。我们来进行对比试验,来发现实现该框架框架的好处和不足。

我们在做一个展示UI的例子,该例子当运行时,点击M键可以显示UI,点击N键可以关闭UI。再点击UI中的角色按钮可以再打开一个角色面板。点击角色面板的升级按钮,可以改变人物的属性数值,并且可以实时的进行面板的更新相应。

效果演示:

unity mvc ui框架 unity mvc框架工作原理_游戏开发_02


我的项目资源可供大家下载:项目资源包免费下载

无框架,普通逻辑代码脚本

主UI脚本

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

public class Main : MonoBehaviour
{
    public Text PlayerText;
    public Text LevelText;
    public Text CoinText;
    public Text JewelText;
    public Text PowerText;
    public Button RoleButton;

    

    private static Main intestMain;

    public static Main IntestMinMain//单例模式
    {
        get
        {
            return intestMain;
        }
    }
    private GameObject Role;
    private GameObject resGameObject;
    void Start()
    {
        SetDate();
        resGameObject = Resources.Load<GameObject>("RoleUI");
        RoleButton.onClick.AddListener(ButtonRole);
    }

    public  void SetDate()
    {
        PlayerText.text = PlayerPrefs.GetString("Name", "玩家名字");
        LevelText.text ="LV. "+ PlayerPrefs.GetInt("Level", 1).ToString();
        CoinText.text = PlayerPrefs.GetInt("Coin", 0).ToString();
        JewelText.text = PlayerPrefs.GetInt("Jewel", 0).ToString();
        PowerText.text=PlayerPrefs.GetInt("Power",10).ToString();
    }

    public static void Showme()//控制自身的显示
    {
        if (intestMain == null)
        {
            GameObject res = Resources.Load<GameObject>("UI");
            GameObject obj = Instantiate(res);
            obj.transform.SetParent(GameObject.Find("Canvas").transform, false);
            intestMain = obj.GetComponent<Main>();
        }
        intestMain.gameObject.SetActive(true);
        intestMain.SetDate();
    }

    public static void Hideme()
    {
        intestMain.gameObject.SetActive(false);
    }

    void ButtonRole()
    {
        if (Role == null)
        {
            Role = Instantiate(resGameObject);
            Role.transform.SetParent(GameObject.Find("Canvas").transform,false);
        }
        Role.SetActive(true);
    }
}

角色UI脚本

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

public class CloseRole : MonoBehaviour
{
    public Button ColoseButton;
    public Button UpgradeButton;
    public Text LevelText;
    public Text CoinText;
    public Text JewelText;
    public Text PowerText;

    private int Level=1;
    private int Coin=0;
    private int Jewel=0;
    private int Power=0;
    void Start()
    {
        ColoseButton.onClick.AddListener(Close);
        SetDate();
        UpgradeButton.onClick.AddListener(UpNumber);
    }

    public void Close()
    {
        gameObject.SetActive(false);
    }

    public void UpNumber()
    {
        Level = PlayerPrefs.GetInt("Level",1) + 1;
        Random random = new Random();
        Coin += random.Next(50, 100);
        Jewel += random.Next(50, 100);
        Power += random.Next(20, 80);
        PlayerPrefs.SetInt("Level",Level);
        PlayerPrefs.SetInt("Coin", Coin);
        PlayerPrefs.SetInt("Jewel", Jewel);
        PlayerPrefs.SetInt("Power", Power);
        SetDate();
        Main.IntestMinMain.SetDate();
        
    }

    public void SetDate()
    {
        LevelText.text = "LV. " + PlayerPrefs.GetInt("Level",1).ToString();
        CoinText.text = PlayerPrefs.GetInt("Coin", 0).ToString();
        JewelText.text = PlayerPrefs.GetInt("Jewel", 0).ToString();
        PowerText.text = PlayerPrefs.GetInt("Power", 10).ToString();
    }

}

摄像机显示脚本

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

public class Show : MonoBehaviour
{
    
    void Start()
    {
        //PlayerPrefs.DeleteAll();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.M))
        {
            Main.Showme();
        }

        if (Input.GetKeyDown(KeyCode.N))
        {
            Main.Hideme();
        }
    }
}

脚本的放置

摄像机及脚本

unity mvc ui框架 unity mvc框架工作原理_unity mvc ui框架_03


主界面及脚本

unity mvc ui框架 unity mvc框架工作原理_unity_04


角色脚本

unity mvc ui框架 unity mvc框架工作原理_游戏_05

MVC框架的运用

Model脚本

把模型的数据都集中起来进行管理操作。并实现更新和保存的方法。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEditor;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using Random = System.Random;

public class ModelUI
{
    //Model只要就是存放数据,存放数据和更新数据,是MVC框架的核心
    //MVC只适用于UI游戏场景的游戏,并不是适合于所有的项目游戏

    private static ModelUI Intenst;
    
    #region 数据集合

    private string playerName;
    public string PlayerName => playerName;

    private int level;
    public int Level => level;

    private int coin;
    public int Coin => coin;

    private int jewel;
    public int Jewel => jewel;

    private int power;

    public int Power => power;

    #endregion

    public event UnityAction<ModelUI> ModelAction;//这个是unity的委托类型。我们要对其进行通知和反馈的操作注册。


    public static ModelUI Getit()//这里是单例模式,只有一个Model。
    {
        if (Intenst==null)
        {
            Intenst=new ModelUI();
            Intenst.SetDate();
        }

        return Intenst;
    }
    //更新数据
    public void SetDate()
    {
        playerName = PlayerPrefs.GetString("Name", "皮学渣");

        level = PlayerPrefs.GetInt("Level", 1);
        coin = PlayerPrefs.GetInt("Coin", 0);
        jewel = PlayerPrefs.GetInt("Jewel", 0);
        power = PlayerPrefs.GetInt("Power", 10);

    }
    
    //点击升级按钮后修改数据
    public void LevelUp()
    {
        level += 1;
        
        Random random=new Random();
        coin += random.Next(10, 30);
        jewel += random.Next(10, 30);
        power += random.Next(10, 30);
        
        SaveDate();
    }

    //保存数据
    public void SaveDate()
    {
        PlayerPrefs.SetInt("Level",level);
        PlayerPrefs.SetInt("Coin",coin);
        PlayerPrefs.SetInt("Jewel",jewel);
        PlayerPrefs.SetInt("Power",power);
        
        //档保存后就自动更新数据
        UpdateInfo();
    }

    
    
    
    public void AddFuction(UnityAction<ModelUI> fun)
    {
        ModelAction += fun;
        
    }
    
    public void SubtrctFuction(UnityAction<ModelUI> fun)
    {
        ModelAction -= fun;
    }
    
    //通知外部更新数据
    public void UpdateInfo()
    {
        if (ModelAction != null)
        {
            ModelAction(this);
        }
    }
}

View脚本

View的主要作用是对于数据的显示处理,并将该脚本放在特定的UI上面。不需要实现按钮的注册事件逻辑

主界面的View脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MainUI:MonoBehaviour
{
    #region View作用
    /*
    view主要就是找UI的控件,对UI控件的信息进行更新,不需要实现按钮的注册事件逻辑
    */
    #endregion

    public Text NameText;
    public Text LevelText;
    public Text CoinText;
    public Text JewelText;
    public Text PowerText;
    public Button Role;

    public void InfoDate(ModelUI model)
    {
        NameText.text = model.PlayerName;
        LevelText.text = model.Level.ToString();
        CoinText.text = model.Coin.ToString();
        JewelText.text = model.Jewel.ToString();
        PowerText.text = model.Power.ToString();
    }
}
角色View脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class RoleUI :MonoBehaviour
{
    
    public Text LevelText;
    public Text CoinText;
    public Text JewelText;
    public Text PowerText;
    public Button UpClick;
    public Button Colose;

    public void InfoDate(ModelUI model)
    {
        LevelText.text = model.Level.ToString();
        CoinText.text = model.Coin.ToString();
        JewelText.text = model.Jewel.ToString();
        PowerText.text = model.Power.ToString();
    }
}

Controller脚本

主界面的Controller脚本

控制器的作用是对UI的事件继续注册,完成代码逻辑的地方。用控制器来进行响应和反馈

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

public class MainController : MonoBehaviour
{
    // Controle主要用来控制UI的显隐,还有逻辑的处理,数据的更新,ui按钮事件的注册

    private MainUI _mainUi;
    
    //1.控制显隐
    private static MainController controller=null;
    public static MainController Controller()
    {
        if (controller == null)
        {
            controller=new MainController();
        }

        return controller;
    }

    public static void ShowMe()
    {
        if (controller == null)
        {
            GameObject res = Resources.Load<GameObject>("UI");
            GameObject obj = Instantiate(res);
            obj.transform.SetParent(GameObject.Find("Canvas").transform,false);
            controller = obj.GetComponent<MainController>();
        }
        controller.gameObject.SetActive(true);
    }

    public static void Hide()
    {
        if (controller != null)
        {
            controller.gameObject.SetActive(false);
        }
    }
    
    //2.注册事件,给UI注册事件,当我们显示UI的时候,就可以和MainUI关联,将MainUI赋值,并给他的按钮注册事件
    //当显示UI的时候,就给他赋值,所以就在start函数进行初始化
    private void Start()
    {
        _mainUi = this.gameObject.GetComponent<MainUI>();
        _mainUi.InfoDate(ModelUI.Getit());
        _mainUi.Role.onClick.AddListener(RoleButton);
        ModelUI.Getit().AddFuction(Info);
    }

    public void RoleButton()
    {
        RpleController.ShowMe();
    }
    
    public void Info(ModelUI date)
    {
        if (_mainUi != null)
        {
            _mainUi.InfoDate(date);
        }
    }

    private void OnDestroy()
    {
        ModelUI.Getit().SubtrctFuction(_mainUi.InfoDate);
    }
}
角色Controller脚本
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RpleController : MonoBehaviour
{
    private RoleUI _roleUi;
    
    
    
    //1.控制显隐
    private static RpleController controller=null;
    public static RpleController Controller()
    {
        if (controller == null)
        {
            controller=new RpleController();
        }

        return controller;
    }

    public static void ShowMe()
    {
        if (controller == null)
        {
            GameObject res = Resources.Load<GameObject>("RoleUI");
            GameObject obj = Instantiate(res);
            obj.transform.SetParent(GameObject.Find("Canvas").transform,false);
            controller = obj.GetComponent<RpleController>();
        }
        controller.gameObject.SetActive(true);
    }

    public static void Hide()
    {
        if (controller != null)
        {
            controller.gameObject.SetActive(false);
        }
    }
    
    //2.注册事件,给UI注册事件,当我们显示UI的时候,就可以和MainUI关联,将MainUI赋值,并给他的按钮注册事件
    //当显示UI的时候,就给他赋值,所以就在start函数进行初始化
    private void Start()
    {
        _roleUi = this.gameObject.GetComponent<RoleUI>();
        _roleUi.InfoDate(ModelUI.Getit());
        _roleUi.Colose.onClick.AddListener(Hide);
        _roleUi.UpClick.onClick.AddListener(LevelUpClick);//这里对Model委托进行添加方法
        ModelUI.Getit().AddFuction(Info);
    }
    
    //3.更新数据
    public void LevelUpClick()
    {
        ModelUI.Getit().LevelUp();
        
    }

    public void Info(ModelUI date)
    {
        if (_roleUi != null)
        {
            _roleUi.InfoDate(date);
        }
    }

    private void OnDestroy()
    {
        ModelUI.Getit().SubtrctFuction(_roleUi.InfoDate);
    }
}

控制主界面的显示脚本

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

public class InputMN : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //PlayerPrefs.DeleteAll();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.M))
        {
            MainController.ShowMe();
        }
        else if(Input.GetKeyDown(KeyCode.N))
        {
            MainController.Hide();
        }
        
        
    }
}

脚本控件物体的连接

主界面的脚本

unity mvc ui框架 unity mvc框架工作原理_游戏开发_06

角色的脚本

unity mvc ui框架 unity mvc框架工作原理_unity mvc ui框架_07


相机添加脚本控制界面的显隐

unity mvc ui框架 unity mvc框架工作原理_游戏_08

总结

通过上面的两者编程方法,不知大家收获多少。
在普通的编程逻辑下。我们把控制该物体的行为都是写在一个脚本里面。控制UI的,按钮的注册,数据的显示更新保存等都是聚集在一个脚本内。
用了MVC框架,各各行为分工严明,具体是干甚的只需要把自己的内用写好就行。在控制器里来进行调用用于反馈通知。
同时MVC框架不是所有的游戏就可以使用,而是那种UI的游戏什么的可以运用,这种编程思想还需要我们用一些实际的项目来操作来去学习。