1、什么是MVVM

借用一下百度百科上对MVVM的介绍,MVVM是Model-View-ViewModel的简写,它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。
 

2、MVVM在unity开发中的应用

MVVM框架应用面十分广泛,通常在前端开发中应用很广,最近看到周围同事在开发WPF时用到了这个框架,抱着好奇的态度来学习一下这个框架,MVVM框架在unity开发中同样适用,在unity中,将每个UI抽象成一个个View,通常我们为每一个UI面板定义一个View,View中包含了该面板中涉及到的UI元素,比如一个Text,一个Button;每一个View都有独立的ViewModel来管理,ViewModel中提供必要的属性和方法来控制View, 而Model只是单纯的定义一个数据模型。前两天在github上发现了这个叫uMVVM的框架,拿来试用了一下,下面分析一下该框架对MVVM模式的设计。
 

3、uMVVM的设计与实现

下载uMVVM后,它提供了一些使用示例:

在这个示例中,有两个panel,就定义了两个view,每个view中定义该界面的元素,比如SetupView:

public class SetupView:UnityGuiView<SetupViewModel>
{ public InputField nameInputField;
public Text nameMessageText; public InputField jobInputField;
public Text jobMessageText; public InputField atkInputField;
public Text atkMessageText; public Slider successRateSlider;
public Text successRateMessageText; public Toggle joinToggle;
public Button joinInButton;
public Button waitButton; public SetupViewModel ViewModel { get { return (SetupViewModel)BindingContext; } } }
可以看到,View中需要指定对应的ViewModel来管理该View,ViewModel中定义的属性需要具备当数据改变时通知订阅者的功能,因此uMVVM对这种属性进行了一层封装,具体设计如下:

public class BindableProperty<T>
{
public delegate void ValueChangedHandler(T oldValue, T newValue); public ValueChangedHandler OnValueChanged; private T _value;
public T Value
{
get
{
return _value;
}
set
{
if (!Equals(_value, value))
{
T old = _value;
_value = value;
ValueChanged(old, _value);
}
}
} private void ValueChanged(T oldValue, T newValue)
{
if (OnValueChanged != null)
{
OnValueChanged(oldValue, newValue);
}
} public override string ToString()
{
return (Value != null ? Value.ToString() : "null");
}
}
可以看到,BindableProperty类中维护一个T类型数据,当T发生变化时,可以通知到订阅者,有了这种属性之后,那么ViewModel就是这样的了:

public class SetupViewModel:ViewModelBase
{
public readonly BindableProperty<string> Name = new BindableProperty<string>();
public readonly BindableProperty<string> Job=new BindableProperty<string>();
public readonly BindableProperty<int> ATK = new BindableProperty<int>();
public readonly BindableProperty<float> SuccessRate=new BindableProperty<float>();
public readonly BindableProperty<State> State=new BindableProperty<State>();
}
uMVVM的设计中,每个View都继承UnityGuiView这个泛型类,UnityGuiView大概的内容是这样:

public abstract class UnityGuiView<T>:MonoBehaviour,IView<T> where T:ViewModelBase
{
private bool _isInitialized;
public bool destroyOnHide;
protected readonly PropertyBinder<T> Binder=new PropertyBinder<T>();
public readonly BindableProperty<T> ViewModelProperty = new BindableProperty<T>(); public T BindingContext
{
get { return ViewModelProperty.Value; }
set
{
if (!_isInitialized)
{
OnInitialize();
_isInitialized = true;
}
//触发OnValueChanged事件
ViewModelProperty.Value = value;
}
} /// <summary>
/// 初始化View,当BindingContext改变时执行
/// </summary>
protected virtual void OnInitialize()
{
//无所ViewModel的Value怎样变化,只对OnValueChanged事件监听(绑定)一次
ViewModelProperty.OnValueChanged += OnBindingContextChanged;
} /// <summary>
/// 当gameObject将被销毁时,这个方法被调用
/// </summary>
public virtual void OnDestroy()
{
if (BindingContext.IsRevealed)
{
Hide(true);
}
BindingContext.OnDestory();
BindingContext = null;
ViewModelProperty.OnValueChanged = null;
} /// <summary>
/// 绑定的上下文发生改变时的响应方法
/// 利用反射+=/-=OnValuePropertyChanged
/// </summary>
public virtual void OnBindingContextChanged(T oldValue, T newValue)
{
Binder.Unbind(oldValue);
Binder.Bind(newValue);
}
}
UnityGuiView中有一个BindingContext的属性, 当使用框架时,需要给View的BindingContext指定对应的ViewModel:

  public class Install:MonoBehaviour
{
// Use this for initialization
public SetupView setupView;
public TestView testView;
void Start()
{
//绑定上下文
setupView.BindingContext=new SetupViewModel();
testView.BindingContext=new TestViewModel();
}
}
在View中,就订阅model数据改变的消息,并定义相应的响应函数:

 public class SetupView:UnityGuiView<SetupViewModel>
{
//......省略ui元素的定义 protected override void OnInitialize()
{
base.OnInitialize();
Binder.Add<string>("Name", OnNamePropertyValueChanged);
Binder.Add<string>("Job",OnJobPropertyValueChanged);
Binder.Add<int>("ATK",OnATKPropertyValueChanged);
Binder.Add<float>("SuccessRate",OnSuccessRatePropertyValueChanged);
Binder.Add<State>("State",OnStatePropertyValueChanged);
} private void OnSuccessRatePropertyValueChanged(float oldValue, float newValue)
{
successRateMessageText.text = newValue.ToString("F2");
} private void OnATKPropertyValueChanged(int oldValue, int newValue)
{
atkMessageText.text = newValue.ToString();
} private void OnJobPropertyValueChanged(string oldValue, string newValue)
{
jobMessageText.text = newValue.ToString();
} private void OnNamePropertyValueChanged(string oldValue, string newValue)
{
nameMessageText.text = newValue.ToString();
}
private void OnStatePropertyValueChanged(State oldValue, State newValue)
{
//dosomething
}

最后看一下其中一个model的定义:

 public class Combatant
{
public int Id { get; set; }
public string Name { get; set; }
public string Job { get; set; }
public float SuccessRate { get; set; }
public State State { get; set; }
}
public enum State
{
JoinIn,
Wait
}

4、总结

本文只大概写了一下uMVVM框架的一些设计和使用方法,不全面,如果感兴趣,可以自行阅读源码,github地址为https://github.com/MEyes/uMVVM
 
如有错误,欢迎指正!

MVVM框架在unity开发中的使用的更多相关文章

  1. 二十八、带给我们一种新的编码思路——EFW框架CS系统开发中的MVC模式探讨

    回<[开源]EFW框架系列文章索引>        EFW框架源代码下载V1.3:http://pan.baidu.com/s/1c0dADO0 EFW框架实例源代码下载:http://p ...

  2. 二十七、EFW框架BS系统开发中的MVC模式探讨

    回<[开源]EFW框架系列文章索引>        EFW框架源代码下载V1.3:http://pan.baidu.com/s/1c0dADO0 EFW框架实例源代码下载:http://p ...

  3. 领域驱动和MVVM应用于UWP开发的一些思考

    领域驱动和MVVM应用于UWP开发的一些思考 0x00 起因 有段时间没写博客了,其实最近本来是根据梳理的MSDN上的资料(UWP开发目录整理)有条不紊的进行UWP学习的.学习中有了心得体会或遇到了问 ...

  4. MVVM 框架解析之双向绑定

    更好的阅读体验,点击 原文地址 MVVM 框架 近年来前端一个明显的开发趋势就是架构从传统的 MVC 模式向 MVVM 模式迁移.在传统的 MVC 下,当前前端和后端发生数据交互后会刷新整个页面,从而 ...

  5. iOS开发中文件的上传和下载功能的基本实现-备用

    感谢大神分享 这篇文章主要介绍了iOS开发中文件的上传和下载功能的基本实现,并且下载方面讲到了大文件的多线程断点下载,需要的朋友可以参考下 文件的上传 说明:文件上传使用的时POST请求,通常把要上传 ...

  6. 使用MVVM框架(avalonJS)进行快速开发

    背景 在运营活动开发中,因为工作的重复性很大,同时往往开发时间短,某些情况下也会非常紧急,导致了活动开发时间被大大压缩,同时有些活动逻辑复杂,数据或者状态变更都需要手动渲染,容易出错,正是因为这些问题 ...

  7. 简单的介绍下WPF中的MVVM框架

    最近在研究学习Swift,苹果希望它迅速取代复杂的Objective-C开发,引发了一大堆热潮去学它,放眼望去各个培训机构都已打着Swift开发0基础快速上手的招牌了.不过我觉得,等同于无C++基础上 ...

  8. 【Unity游戏开发】浅谈Unity游戏开发中的单元测试

    一.单元测试的定义与作用 单元测试定义:单元测试在传统软件开发中是非常重要的工具,它是指对软件中的最小可测试单元进行检查和验证,一般情况下就是对代码中的一个函数去进行验证,检查它的正确性.一个单元测试 ...

  9. 浅析前端开发中的 MVC/MVP/MVVM 模式

    MVC,MVP和MVVM都是常见的软件架构设计模式(Architectural Pattern),它通过分离关注点来改进代码的组织方式.不同于设计模式(Design Pattern),只是为了解决一类 ...

随机推荐

  1. TVS二极管

    TVS管命名规则: TVS管的型号由三部分组成:系列名+电压值+单/双向符号 系列名代表不同的峰值脉冲功率和封装形式     ① SMAJ.SMBJ.SMCJ.SMDJ表示贴片封装:分别代表的峰值脉冲 ...

  2. centos救援模式实验笔记

    1.  首先在BIOS中把启动选项设置成DVD光驱启动或者USB启动也是可以的 2.  从光盘启动之后再出现的选项中选择“Rescue installed system”然后按回车确认,具体图下图: ...

  3. iOS图片按比例显示

    只需加这么一段代码,如下: imageView.contentMode = UIViewContentModeScaleAspectFit; imageView.autoresizesSubviews ...

  4. 集成算法(chapter 7 - Hands on machine learning with scikit learn and tensorflow)

    Voting classifier 多种分类器分别训练,然后分别对输入(新数据)预测/分类,各个分类器的结果视为投票,投出最终结果: 训练: 投票: 为什么三个臭皮匠顶一个诸葛亮.通过大数定律直观地解 ...

  5. 使用 xUnit 编写 ASP.NET Core WebAPI单元测试

    本文使用xUnit对ASP.NET Core WebAPI做单元测试,使用HttpClient的同步和异步请求,下面详细介绍xUnit的使用过程: 一.创建示例项目 模板为我们自动创建了一个Value ...

  6. 日期时间类:Date,Calendar,计算类:Math

    日期时间类 计算机如何表示时间? 时间戳(timestamp):距离特定时间的时间间隔. 计算机时间戳是指距离历元(1970-01-01 00:00:00:000)的时间间隔(ms). 计算机中时间2 ...

  7. 「PKUSC2018」主斗地(暴搜)

    这道斗地主比 \(PKUWC\) 那道可做多了... 我们用 \(NOIP\) 那道斗地主的思路:暴搜出三代和四代,贪心出散牌. 还有jry为什么要出xx网友而不出他的另一个老婆 我们发现两个人的每回 ...

  8. Python 生成器, 迭代器, 可迭代对象的区别

    1.可迭代对象 在python中, 一切皆对象, 但凡是可以用for循环进行遍历取值的对象都可以称之为可迭代对象, 可迭代对象在程序的一个执行周期中,可以无限轮次的进行循环遍历 2.迭代器 a.一个可 ...

  9. updateByPrimaryKey 和 updateByPrimaryKeySelective

    1. 数据库记录 2. updateByPrimaryKey Preparing: UPDATE t_token_info SET entity_id = ?,entity_type = ?,time ...

  10. 重拾 BFC、IFC、GFC、FFC

    温故知新,巩固基础 从 FC 开始 FC,Formatting Context,格式化上下文,是 W3C CSS2.1 规范中的一个概念,定义的是页面中一块渲染区域,并且有一套渲染规则,它决定了其子元 ...