当前位置:   article > 正文

Unity | 框架MVC_unity mvc框架

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层

  1. using System;
  2. using UnityEngine;
  3. public class Model
  4. {
  5. // 单例
  6. private static Model instance;
  7. public static Model Instance
  8. {
  9. get
  10. {
  11. if (instance == null)
  12. {
  13. instance = new Model();
  14. instance.Init();
  15. }
  16. return instance;
  17. }
  18. }
  19. // 数据
  20. private int coinCount;
  21. public int CoinCount
  22. {
  23. get { return coinCount; }
  24. }
  25. // 数据操作:初始化、更新、保存
  26. private void Init()
  27. {
  28. coinCount = PlayerPrefs.GetInt("CoinCount", 0);
  29. }
  30. public void UpdateCoinCount()
  31. {
  32. ++coinCount;
  33. Save();
  34. }
  35. private void Save()
  36. {
  37. PlayerPrefs.SetInt("CoinCount", coinCount);
  38. CallEvent();
  39. }
  40. // 事件:用于通知Controller进行更新View
  41. private event Action<Model> ModelEvent;
  42. public void AddEventListener(Action<Model> function)
  43. {
  44. ModelEvent += function;
  45. }
  46. public void RemoveEventListener(Action<Model> function)
  47. {
  48. ModelEvent -= function;
  49. }
  50. private void CallEvent()
  51. {
  52. ModelEvent?.Invoke(this);
  53. }
  54. }

2.View层

  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. public class View : MonoBehaviour
  4. {
  5. //提供UI控件
  6. public Text coinText;
  7. public Button addCoinButton;
  8. //提供更新UI控件的方法
  9. public void UpdateCoin(Model model)
  10. {
  11. coinText.text = model.CoinCount.ToString();
  12. }
  13. }

3.Controller层

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

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class Controller : MonoBehaviour
  5. {
  6. //controller控制view
  7. private View view;
  8. private static Controller controller;
  9. public static Controller Instance
  10. {
  11. get
  12. {
  13. return controller;
  14. }
  15. }
  16. //1.面板显示隐藏
  17. public static void Show()
  18. {
  19. if (controller == null)
  20. {
  21. var temp = Resources.Load<GameObject>("Prefabs/UIPanel");
  22. var go = Instantiate(temp);
  23. go.transform.parent = GameObject.Find("Canvas").transform;
  24. go.transform.localPosition = Vector3.zero;
  25. go.transform.localScale = Vector3.one;
  26. controller = go.GetComponent<Controller>();
  27. }
  28. controller.gameObject.SetActive(true);
  29. }
  30. public static void Hide()
  31. {
  32. if (controller != null)
  33. {
  34. controller.gameObject.SetActive(false);
  35. }
  36. }
  37. void Start()
  38. {
  39. view = GetComponent<View>();
  40. //2.首次更新面板数据
  41. view.UpdateCoin(Model.Instance);
  42. //3.事件监听,更新数据
  43. view.addCoinButton.onClick.AddListener(() =>
  44. {
  45. Model.Instance.UpdateCoinCount();
  46. });
  47. Model.Instance.AddEventListener(UpdateCoin);
  48. }
  49. private void UpdateCoin(Model model)
  50. {
  51. //2.更新面板数据
  52. view.UpdateCoin(model);
  53. }
  54. private void OnDestroy()
  55. {
  56. Model.Instance.RemoveEventListener(UpdateCoin);
  57. }
  58. }

四、MVC框架测试

  1. using UnityEngine;
  2. public class TestMVC : MonoBehaviour
  3. {
  4. void Update()
  5. {
  6. if (Input.GetMouseButtonDown(0))
  7. {
  8. Controller.Show();
  9. }
  10. if (Input.GetMouseButtonDown(1))
  11. {
  12. Controller.Hide();
  13. }
  14. }
  15. }

五、知识补充

  1. private event Action<Model> ModelEvent;
  2. public void AddEventListener(Action<Model> function)
  3. {
  4. ModelEvent += function;
  5. }
  6. public void RemoveEventListener(Action<Model> function)
  7. {
  8. ModelEvent -= function;
  9. }
  10. private void CallEvent()
  11. {
  12. ModelEvent?.Invoke(this);
  13. }

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

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/766367
推荐阅读
相关标签
  

闽ICP备14008679号