简介

MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发,通过使用这种设计模式可以有效的实现各个功能的模块化,也可以更好地实现模块内部和模块间数据、业务逻辑、交互界面的分离。

通过这种形式的分离可以保证我们在开发应用的过程中能够专注于一个方面,例如在开发Model的时候只需要关注如何设计数据结构、提供数据修改的接口以及数据发生变动时通知对应的显示界面;在开发Controller的时候只需要关注业务逻辑如何实现,按照需求修改对应Model的数据;开发View的时候只需要监听数据的变化让UI做出响应,提供交互功能实现用户对数据的修改。

详细介绍

组成部分

M(Model)—— 模型

Model中包含了这一个业务模块所包含的数据结构,这里所说的数据结构并不是单纯的保存在用户私有数据中的数据结构(如:当前关卡,金币余额等),而是在应用运行过程中根据用户保存于本地(或服务器)上的私有数据动态创建的数据,是内存中的数据结构。

除了提供数据结构外Model还需要在数据发生变化时通知View层,使其做出响应。Unity中这一步可以通过委托来实现,下文会介绍到。

V(View)—— 视图

View中定义了数据要以何种形式展示,是数据的窗口。

需要注意的是View和Model并非一对一的关系,而是多对多的关系,一个View可能会展示几个Model的数据,同样一个Model的数据也可能会在多个View中展示。

举个栗子,在游戏主界面上可能包含有金币余额、钻石余额、签到天数、装备信息等等,这就涉及到了用户模块、签到模块、装备模块。如果强行为每个模块对应一个View的化可能会导致整个UI架构变琐碎、难以维护。

View层并不等于UI界面,可以把它抽象为数据展示层,在对玩家角色的位置、装备信息、血量等数据进行展示时,View层就变成了游戏场景,而非UI界面。

View同样还需要提供如按钮点击、射线检测等功能,是用户通过Controller对数据进行修改的起点。

C(Controller)—— 业务控制器

Controller中规定了当用户传入参数或进行操作时应该以何种方式修改Model中的数据,是修改Model中数据唯一的入口。

Controller与View可以是一对一的关系,也就是说为一个Model配一个Controller作为它的管理类,这种方式可以防止Controller对其他模块Model中数据的引用,如果必须访问则需要通过对应的Controller进行访问。

代码实现

BaseModel

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LitJson;namespace MVCBase
{public delegate void OnValueChange<V>(V val);/// <summary>/// Model基类/// </summary>/// <typeparam name="D">本地数据泛型</typeparam>public class BaseModel<T, D> : Singleton<T> where T : new() where D : new(){/// <summary>/// 本地存储数据的Key, 默认为""/// </summary>protected virtual string GetLocalDataKey(){return "";}/// <summary>/// 本地数据/// </summary>protected D localData = new D();/// <summary>/// 初始化流程,请务必在使用前调用/// </summary>public void Init(){// 先读取本地数据GetLocalData();// 在初始化Model中使用到的数据结构InitData();}private void GetLocalData(){if (GetLocalDataKey() == ""){return;}string localDataStr = PlayerPrefs.GetString(GetLocalDataKey(), "");if (localDataStr == null || localDataStr == ""){return;}localData = JsonMapper.ToObject<D>(localDataStr);}/// <summary>/// 初始化本地数据/// </summary>protected virtual void InitData() { }protected void SaveLocalData(){if (GetLocalDataKey() == ""){return;}if (localData == null){Debug.LogError("local data is null, key: " + GetLocalDataKey());return;}string localDataStr = JsonMapper.ToJson(localData);PlayerPrefs.SetString(GetLocalDataKey(), localDataStr);}}
}public class BaseLocalData { }

TestModel

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MVCBase;/// <summary>
/// 测试模块
/// 因为不需要本地数据所以对应泛型选择Object,LocalDataKey用默认值
/// </summary>
public class TestModel : BaseModel<TestModel, Object>
{/// <summary>/// 金币数额变化时执行委托/// </summary>public OnValueChange<int> OnCoinChange;/// <summary>/// 钻石数额变化时执行委托/// </summary>public OnValueChange<int> OnDiamondChange;private int coin = 0;public int Coin{get{return coin;}set{coin = value;if (OnCoinChange != null){OnCoinChange(coin);}}}private int diamond = 0;public int Diamond{get{return diamond;}set{diamond = value;if (OnDiamondChange != null){OnDiamondChange(diamond);}}}}

TestController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 测试Controller
/// 提供修改金币和钻石的接口
/// </summary>
public class TestController : MonoSingleton<TestController>
{private void Start(){TestModel.Instance.Init();}/// <summary>/// 修改金币的接口/// </summary>/// <param name="delat"></param>public void ChangeCoin(int delat){TestModel.Instance.Coin += delat;}/// <summary>/// 修改钻石的接口/// </summary>/// <param name="delat"></param>public void ChangeDiamond(int delat){TestModel.Instance.Diamond += delat;}
}

TestView

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;/// <summary>
/// 测试View
/// CoinText和DiamondText负责金币和钻石数量的显示
/// 在场景中添加按钮绑定修改金币和钻石的接口
/// </summary>
public class TestView : MonoBehaviour
{public Text coinText;public Text diamondText;private void Start(){TestModel.Instance.OnCoinChange += RefreshCoin;TestModel.Instance.OnDiamondChange += RefreshDiamond;coinText.text = "金币:" + TestModel.Instance.Coin;diamondText.text = "钻石:" + TestModel.Instance.Diamond;}private void RefreshCoin(int value){coinText.text = "金币:" + value;}private void RefreshDiamond(int value){diamondText.text = "钻石:" + value;}/// <summary>/// 添加金币的接口/// </summary>public void AddCoin(){TestController.Instance.ChangeCoin(100);}/// <summary>/// 扣除金币的接口/// </summary>public void ReduceCoin(){TestController.Instance.ChangeCoin(-80);}/// <summary>/// 添加钻石的接口/// </summary>public void AddDiamond(){TestController.Instance.ChangeDiamond(20);}/// <summary>/// 扣除钻石的接口/// </summary>public void ReduceDiamond(){TestController.Instance.ChangeDiamond(-50);}
}

项目地址:MVCFrame: 在Unity中实现MVC架构

运行效果:

点击对应按钮即可修改Model中的数据,数据变化的同时会通知UI界面刷新数据显示

在Unity中实现基础的MVC架构相关推荐

  1. Unity 中带你写MVC架构

    1.什么是MVC MVC分别代表Model - View - Controller Model - 模型层,也就是说,他只负责数据 View - 视图层,也就是说,他只负责更新UI Controlle ...

  2. 【贪玩巴斯】Unity3D初学圣经(三)—— unity中的基础概念——scene场景,component组件,assets文件夹和Material材质,Mesh Renderer与shader

    [贪玩巴斯]Unity3D初学圣经 三-- unity中的基础概念--scene场景,component组件与assets文件夹和Material材质以及Mesh Renderer 和 shader ...

  3. unity入门精要之第6 章 Unity 中的基础光照--环境光和自发光

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.Unity 中的环境光和自发光 二.在Unity Shader 中实现漫反射光照模型 参考 前言 但这种模型有很多局限性.首先,有很 ...

  4. Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照

    转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交 ...

  5. Unity 中的基础光照

    通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑三种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交:一些光被物体吸收了,而另一些光被散射到其他方向. 最后,摄像 ...

  6. unity入门精要之第6 章 Unity 中的基础光照---实现高光反射光照模型

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 参考 前言 在6.2.4 节中,我们给出了基本光照模型中高光反射部分的计算公式: 从公式可以看出,要计算高光反射需要知道4 个参数:入射 ...

  7. unity入门精要之第6 章 Unity 中的基础光照概述-1

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 6.1 我们是如何看到这个世界的 6.2 标准光照模型 参考 前言 渲染总是围绕着一个基础问题:我们如何决定一个像素的颜色?从宏观上来说 ...

  8. MVC架构在Asp.net中的应用和实现

    MVC架构在Asp.net中的应用和实现 摘要:本文主要论述了MVC架构的原理.优缺点以及MVC所能为Web应用带来的好处.并以"成都市信息化资产管理系统"框架设计为例,详细介绍其 ...

  9. Photon在unity中的使用

    ps:期末老师要求的一篇3000字的玩具级别论文,基本是官网和api手册原本就有的.基本我就是个搬运工,不知道有什么用,就先扔上来了.用的是writage,让word转为markdown,可能会出现一 ...

最新文章

  1. python 物理学中的应用_利用python求解物理学中的双弹簧质能系统详解
  2. 用html写出生日蛋糕,纯HTML5+CSS3制作生日蛋糕代码
  3. 在基于Spring MVC的应用程序中配置favicon.ico
  4. VS2019编译 当前最新版chromium
  5. 网页中、英文安全字体选择及设置
  6. [导入]WCF后传系列(8):深度通道编程模型Part 1—设计篇
  7. 利用正则计算输入内容的长度
  8. 机器学习基础(二十五)—— Feature Selection
  9. 从 阿西莫夫机器人三大定律 谈起
  10. 【UOJ】#37. 【清华集训2014】主旋律
  11. ftp工具破解版,细数6个ftp工具破解版
  12. java-高级编程课-实验题集标答整理
  13. Wamp的介绍和配置,解决安装时一些错误和配置上的一些需要,轻轻松松搭建以为window系统的服务器
  14. 2021年最值得推荐的29个开源软件,想提升自己的程序员赶快收藏
  15. 摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人”
  16. CnOpenData中国上市公司全部公告数据
  17. R绘图 第十篇:绘制散点图(高级)
  18. Linux下的Web开发工具(一)
  19. 力士乐触摸屏维修VCP20.2DUN-003-PB-NN-PW
  20. Spring Cloud Ribbon 全解 (4) - 基本组件实现源码(2)

热门文章

  1. AltiumDesigner生成彩色电路图PDF
  2. steam搬砖项目,怎么做?详细解答
  3. 测试工程师面试之项目介绍
  4. x ,1/x的关系; 反函数的实质:xy可以互换,就是进行坐标轴变化,就是关于y=x对称 反函数性质:f-1(f(x))=x; 反三角函数‘
  5. Linux操作系统管理公共基础——积累
  6. python操作excel报错,Resource gutenberg not found. Please use the NLTK Downloader to obtain the resouce
  7. 主线剧情03-NXP-i.MX系列的u-boot移植基础详解
  8. 北京工业大学 大一C语言课程设计--四子棋(Bingo)(连子游戏)in TurboC 3.0
  9. 年后离职潮,我该如何优雅的跟老板提离职?
  10. 京东企业采购服务升级 技术能力以软件形式输出