• 【Unity 框架】QFramework v1.0 使用指南 架构篇:02. QFramework 的 MVC | Unity 游戏框架 | Unity 游戏开发 | Unity 独立游戏


    QFramework 基于 MVC 的开发模式

    所以我们先从最熟知的 MVC 架构开始着手 QFramework 的学习。

    我们先做一个非常简单的计数器应用。

    首先我们使用 UGUI 创建一个最简单的界面,如下图所示:

    image.png

    场景结构如下所示:

    image.png

    复制完之后,我们创建一个脚本叫做 CounterAppController,代码如下:

    using UnityEngine;
    using UnityEngine.UI;
    
    namespace QFramework.Example
    {
        // Controller
        public class CounterAppController : MonoBehaviour
        {
            // View
            private Button mBtnAdd;
            private Button mBtnSub;
            private Text mCountText;
            
            // Model
            private int mCount = 0;
    
            void Start()
            {
                // View 组件获取
                mBtnAdd = transform.Find("BtnAdd").GetComponent<Button>();
                mBtnSub = transform.Find("BtnSub").GetComponent<Button>();
                mCountText = transform.Find("CountText").GetComponent<Text>();
                
                
                // 监听输入
                mBtnAdd.onClick.AddListener(() =>
                {
                    // 交互逻辑
                    mCount++;
                    // 表现逻辑
                    UpdateView();        
                });
                
                mBtnSub.onClick.AddListener(() =>
                {
                    // 交互逻辑
                    mCount--;
                    // 表现逻辑
                    UpdateView();
                });
                
                UpdateView();
            }
            
            void UpdateView()
            {
                mCountText.text = mCount.ToString();
            }
        }
    }
    

    代码很简单,这是一个非常简易的 MVC 的实现。

    我们将此脚本挂在 Canvas 节点上,运行 Unity 结果如下:

    282fcc3c-96fa-46e1-b4c6-7f4528b04271.gif

    非常简单。

    此时我们还没有导入我们的 QFramework,不着急,我们先看看代码中所介绍的概念。

    首先是 Model、View、Controller

    Model 的代码如下:

    // Model
    private int mCount = 0;
    

    非常简单,只有一个成员变量,但是在这里它其实并不算是一个 Model,他只是要在 View 中显示的一个数据而已,具体为什么不是 Model 我们在后边再说。

    View 的代码如下:

    // View
    private Button mBtnAdd;
    private Button mBtnSub;
    private Text mCountText;
    

    View 的代码也很简单,View 在 QFramework 的 MVC 定义里就是提供关键组件的引用,比如这三个组件是要在 Controller 代码里要用到的。而其他的例如 Canvas Scaler 等这些组件目前 Controller 不需要,所以就不用声明。

    Controller 的代码,如下:

    void Start()
    {
        ...
          
        // 监听输入
        mBtnAdd.onClick.AddListener(() =>
        {
            // 交互逻辑
            mCount++;
            // 表现逻辑
            UpdateView();        
        });
                
        mBtnSub.onClick.AddListener(() =>
        {
            // 交互逻辑
            mCount--;
            // 表现逻辑
            UpdateView();
        });
                
        UpdateView();
    }
            
    void UpdateView()
    {
        mCountText.text = mCount.ToString();
    }
    

    以上就是 Controller 的代码。

    好了,我们回头再看下完整代码。

    using UnityEngine;
    using UnityEngine.UI;
    
    namespace QFramework.Example
    {
        // Controller
        public class CounterAppController : MonoBehaviour
        {
            // View
            private Button mBtnAdd;
            private Button mBtnSub;
            private Text mCountText;
            
            // Model
            private int mCount = 0;
    
            void Start()
            {
                // View 组件获取
                mBtnAdd = transform.Find("BtnAdd").GetComponent<Button>();
                mBtnSub = transform.Find("BtnSub").GetComponent<Button>();
                mCountText = transform.Find("CountText").GetComponent<Text>();
                
                
                // 监听输入
                mBtnAdd.onClick.AddListener(() =>
                {
                    // 交互逻辑
                    mCount++;
                    // 表现逻辑
                    UpdateView();        
                });
                
                mBtnSub.onClick.AddListener(() =>
                {
                    // 交互逻辑
                    mCount--;
                    // 表现逻辑
                    UpdateView();
                });
                
                UpdateView();
            }
            
            void UpdateView()
            {
                mCountText.text = mCount.ToString();
            }
        }
    }
    

    目前像计数器这样的逻辑,以上的代码完全没有问题。

    但是我们要用发展的眼光看待问题。

    假如这是一个初创项目,那么接下来很有可能需要添加大量的业务逻辑。

    其中很有可能让 mCount 在多个 Controller 中使用,甚至需要针对 mCount 这个数据写一些其他逻辑,比如增加 mCount 则增加 5 个分数,或者 mCount 需要存储等,总之 mCount 在未来可能会发展成一个需要共享的数据,而 mCount 目前只属于 CounterAppController,显然在未来这是不够用的。

    我们就需要让 mCount 成员变量变成一个共享的数据,最快的做法是吧 mCount 变量变成静态变量或者单例,但是这样虽然写起来很快,但是在后期维护额度时候会产生很多的问题。

    而 QFramework 架构提供了 Model 的概念。

    我们来使用一下。

    我们先导入 QFramework 架构。

    导入 QFramework 的方式非常简单,只需要复制 QFramework.cs 的代码到 Unity 工程中即可。

    QFramework.cs 地址:

    导入之后,我们将 CounterAppController 的代码改成如下:

    using UnityEngine;
    using UnityEngine.UI;
    
    namespace QFramework.Example
    {
        
        // 1. 定义一个 Model 对象
        public class CounterAppModel : AbstractModel
        {
            public int Count;
            
            protected override void OnInit()
            {
                Count = 0;
            }
        }
    
    
        // 2.定义一个架构(提供 MVC、分层、模块管理等)
        public class CounterApp : Architecture<CounterApp>
        {
            protected override void Init()
            {
                // 注册 Model
                this.RegisterModel(new CounterAppModel());
            }
        }
    
        // Controller
        public class CounterAppController : MonoBehaviour , IController /* 3.实现 IController 接口 */
        {
            // View
            private Button mBtnAdd;
            private Button mBtnSub;
            private Text mCountText;
            
            // 4. Model
            private CounterAppModel mModel;
    
            void Start()
            {
                // 5. 获取模型
                mModel = this.GetModel<CounterAppModel>();
                
                // View 组件获取
                mBtnAdd = transform.Find("BtnAdd").GetComponent<Button>();
                mBtnSub = transform.Find("BtnSub").GetComponent<Button>();
                mCountText = transform.Find("CountText").GetComponent<Text>();
                
                
                // 监听输入
                mBtnAdd.onClick.AddListener(() =>
                {
                    // 6. 交互逻辑
                    mModel.Count++;
                    // 表现逻辑
                    UpdateView();        
                });
                
                mBtnSub.onClick.AddListener(() =>
                {
                    // 7. 交互逻辑
                    mModel.Count--;
                    // 表现逻辑
                    UpdateView();
                });
                
                UpdateView();
            }
            
            void UpdateView()
            {
                mCountText.text = mModel.Count.ToString();
            }
    
            // 3.指定架构
            public IArchitecture GetArchitecture()
            {
                return CounterApp.Interface;
            }
    
            private void OnDestroy()
            {
                // 8. 将 Model 设置为空
                mModel = null;
            }
        }
    }
    

    好了,代码引入了两个新的概念,一个是 Architecture,另一个是 Model。

    Architecture 用于管理模块,或者说 Architecture 提供一整套架构的解决方案,而模块管理和提供 MVC 只是其功能的一小部分。

    我们运行一下 Unity 结果如下:

    282fcc3c-96fa-46e1-b4c6-7f4528b04271.gif

    运行正确。

    好了,我们上手了 QFramework 提供的 MVC 架构。

    这里要注意一点,Model 的引入是为了解决数据共享的问题,而不是说单只是为了让数据和表现分离,这一点是非常重要的一点。

    数据共享分两种:空间上的共享和时间上的共享。

    空间的共享很简单,就是多个点的代码需要访问 Model 里的数据。

    时间上的共享就是存储功能,将上一次关闭 App 之前的数据存储到一个文件里,这次打开时获得上次关闭 App 之前的数据。

    虽然我们上手了 MVC,但是这样的 MVC 还有很多问题,我们下一篇继续解决。

    更多内容

  • 相关阅读:
    ZROI NOI2019集训汇总
    牛客 在二叉树中找到累加和为指定值的最长路径长度
    牛客 遍历二叉树的神级方法
    牛客 打印二叉树边界节点
    牛客 实现二叉树先序,中序和后序遍历
    LeetCode K个一组翻转链表
    LeetCode 相交链表&环形链表II
    LeetCode 分隔链表
    LeetCode 复制带随机指针的链表
    LeetCode 回文链表
  • 原文地址:https://www.cnblogs.com/liangxiegame/p/16798114.html
Copyright © 2020-2023  润新知