Unity | 框架MVC

目录

一、MVC介绍

二、搭建UI界面

三、代码实现

1.Model层

2.View层

3.Controller层

四、MVC框架测试

五、知识补充


一、MVC介绍

  1. model:数据层。界面展示的数据(需要进行初始化、更新、保存、事件通知等操作),单例模式,不必继承MonoBehaviour。
  2. view:界面层。寻找UI,提供更新UI控件的方法,供controller调用。要挂在预制体上。
    (1)MVC是对M和V层进行了解耦,但没有完全解耦,从而诞生了MVP:对M和V层完全解耦。
    (2)MVC里view还是具备直接得到model的权限的,MVP框架是完全把视图跟模型分离了。
  3. controller:处理业务逻辑。控制View的显隐及更新,事件监听及取消。要挂在预制体上。
    (1)注意:物体隐藏时,OnDestroy不会被调用。
    (2)一个view对应一个controller。

二、搭建UI界面

        搭建如下的UI界面,并制作成预制体,并放于Resources\Prefabs目录。

三、代码实现

        创建三个脚本:Model.cs、View.cs、Controller.cs。并将View.cs、Controller.cs挂于预制体上。

1.Model层

using System;
using UnityEngine;

public class Model
{
    // 单例
    private static Model instance;
    public static Model Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Model();
                instance.Init();
            }
            return instance;
        }
    }


    // 数据
    private int coinCount;
    public int CoinCount  
    {
        get { return coinCount; }
    }


    // 数据操作:初始化、更新、保存
    private void Init()
    {
        coinCount = PlayerPrefs.GetInt("CoinCount", 0);
    }
    public void UpdateCoinCount()
    {
        ++coinCount;
        Save();
    }
    private void Save()
    {
        PlayerPrefs.SetInt("CoinCount", coinCount);
        CallEvent();
    }


    // 事件:用于通知Controller进行更新View
    private event Action<Model> ModelEvent;
    public void AddEventListener(Action<Model> function)
    {
        ModelEvent += function;
    }
    public void RemoveEventListener(Action<Model> function)
    {
        ModelEvent -= function;
    }
    private void CallEvent()
    {
        ModelEvent?.Invoke(this);
    }
}

2.View层

using UnityEngine;
using UnityEngine.UI;

public class View : MonoBehaviour
{
    //提供UI控件
    public Text coinText;

    public Button addCoinButton;

    //提供更新UI控件的方法
    public void UpdateCoin(Model model)
    {
        coinText.text = model.CoinCount.ToString();
    }
}

3.Controller层

        一个UI预制体对应一个View、一个Controller。

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

public class Controller : MonoBehaviour
{
    //controller控制view
    private View view;

    private static Controller controller;
    public static Controller Instance
    {
        get
        {
            return controller;
        }
    }

    //1.面板显示隐藏
    public static void Show()
    {
        if (controller == null)
        {
            var temp = Resources.Load<GameObject>("Prefabs/UIPanel");
            var go = Instantiate(temp);
            go.transform.parent = GameObject.Find("Canvas").transform;
            go.transform.localPosition = Vector3.zero;
            go.transform.localScale = Vector3.one;
            controller = go.GetComponent<Controller>();
        }
        controller.gameObject.SetActive(true);

    }

    public static void Hide()
    {
        if (controller != null)
        {
            controller.gameObject.SetActive(false);
        }
    }

    void Start()
    {
        view = GetComponent<View>();

        //2.首次更新面板数据
        view.UpdateCoin(Model.Instance);


        //3.事件监听,更新数据
        view.addCoinButton.onClick.AddListener(() =>
        {
            Model.Instance.UpdateCoinCount();
        });
        Model.Instance.AddEventListener(UpdateCoin);
    }

    private void UpdateCoin(Model model)
    {
        //2.更新面板数据
        view.UpdateCoin(model);
    }


    private void OnDestroy()
    {
        Model.Instance.RemoveEventListener(UpdateCoin);
    }
}

四、MVC框架测试

using UnityEngine;

public class TestMVC : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Controller.Show();
        }
        if (Input.GetMouseButtonDown(1))
        {
            Controller.Hide();
        }
    }
}

五、知识补充

    private event Action<Model> ModelEvent;
    public void AddEventListener(Action<Model> function)
    {
        ModelEvent += function;
    }
    public void RemoveEventListener(Action<Model> function)
    {
        ModelEvent -= function;
    }
    private void CallEvent()
    {
        ModelEvent?.Invoke(this);
    }

        在C#中,event关键字用于声明一个事件,它本质上是一种特殊的多播委托。`ModelEvent`在这里是一个事件,当你对其使用`+=`操作符时,你实际上是将一个回调方法添加到委托的调用列表中。如果你注册了多个回调,那么这些回调方法就会被添加到`ModelEvent`的调用链中。

        当调用`ModelEvent?.Invoke(this);`时,以下是在底层发生的事情:

  1. 空值检查:`?.`是C# 6.0中引入的空条件运算符。它在尝试调用方法或访问成员之前会检查左侧的对象是否为`null`。如果`ModelEvent`不为`null`,那么调用继续;如果为`null`,那么调用就不会执行,整个表达式的结果也是`null`。
  2. Invoke方法:`Invoke`是`MulticastDelegate`类的一个方法,它负责同步地调用委托链中的每个回调方法。`this`关键字是传递给每个回调方法的参数,表示事件的发起者。
  3. 多播委托的调用链:`ModelEvent`作为一个多播委托,可以持有对多个方法的引用。当你调用`Invoke`时,它按照注册的顺序调用这些方法。如果调用链中的任何一个方法抛出异常,那么后续的方法调用将不会执行,除非你捕获并处理了这个异常。
  4. 线程安全性:虽然`?.`操作符提供了对`null`的检查,但这并不保证线程安全性。如果在检查`ModelEvent`之后和调用`Invoke`之前,另一个线程将`ModelEvent`设置为`null`,那么仍然会抛出`NullReferenceException`。在多线程环境中,通常需要额外的同步机制来确保线程安全。
  5. 事件的触发:如果`ModelEvent`不为空,`Invoke`会触发事件,即调用所有注册的回调方法。这些方法将按照它们被添加到委托中的顺序被调用。

        在C#中,事件的使用是一种很好的设计模式,它允许对象通知其他对象发生了某些事情,而不需要知道这些对象是谁或者它们要做什么。这有助于保持代码的解耦和灵活性。

 

  • 7
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Unity游戏中,MVC框架可以帮助我们更好地管理UI。MVC是一种将代码的功能进行划分的设计框架,主要原理是将软件用户界面和业务逻辑分离,提高代码的可扩展性、可复用性、可维护性和灵活性。 在Unity中,我们可以将MVC框架应用到游戏的UI设计中。举个例子来说,当游戏要发布节日活动,并且需要相应地更改游戏UI时,使用MVC框架可以将UI的功能分开,达到低耦合的效果。这样,当替换UI时,其他功能不会受到影响,提高游戏的质量。 在Unity开发过程中,许多公司都使用了MVC的逻辑模式,即数据模型-视图-控制器。数据模型负责存储和管理游戏数据,视图负责显示用户界面,而控制器负责处理用户输入和更新数据模型。通过将这些功能分离,我们可以更好地组织和管理UI代码,提高开发效率。 所以,通过应用MVC框架,我们可以更好地管理Unity游戏的UI,提高代码的可维护性和可扩展性,同时也能提高游戏的质量和用户体验。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【Unity3D日常开发】Unity3d中使用MVC框架](https://blog.csdn.net/q764424567/article/details/83788696)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Unity框架——MVC框架](https://blog.csdn.net/Htlas/article/details/79076201)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

烫青菜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值