Mvvm In Unity

扫码查看

MVVM架构在Unity中的实践

介绍并比较MVC、MVP、MVVM等几种常见架构。针对各架构尤其是MVVM架构,介绍一些在Unity中的实践方案。简要分析各视图架构适合的应用场景,以及各实现方案的优缺点。

#零、MV*架构介绍

MVC

MVP

MVVM

#一、几个概念

1、程序复杂度

  • 复杂度的性质:固有复杂度、人为复杂度
  • 消灭人为复杂度!
  • 固有复杂度无法降低,但是可以拆解。

  • 简化业务复杂性,消除偶然复杂性(解决业务根本复杂性过程中衍生出的复杂性)。
  • 找出稳定的问题,稳定的问题才有稳定的方案。

2、拆解原则

  • 简单simple。不复杂。不是容易easy,更不是随意。
  • 边界清晰。专注点边界!权责边界!概念边界!(好开发,好变更,好拓展)

复杂与混乱complicate vs chaos简洁与容易simple vs easyeasy vs simplecomplect vs compose。compose if not only code organization。

  • 语义原则。用语义去编程,语法只是用来表达语义。
  • 权责平衡原则。层次/模块的权责应当同步。
  • 偏好自由原则。//好的框架/抽象设计:让偏好成为偏好,而不是限制。确定好限制和自由的界限。

3、程序层次

  • 业务组件:具体界面设计和逻辑实现。一个弹窗,一个判定逻辑等。
  • 业务系统:将多个业务组件组织在一起,组成一个可使用的业务系统。活动系统、战斗系统等。
  • 业务框架:将多个业务系统组织在一起,组成一个完整的游戏/程序。解决如何规划业务系统,各个业务系统的生命周期,存在形式。(前端特有,微服务架构用系统架构来实现此层)
  • 程序架构:提供一套即插即用的代码组织方式。解决某段代码应该放在哪里、代码之间如何组织、如何解耦等问题。(极端的情况:无架构,也是一种即插即用。各种单例。)(后端比如消息队列架构)
  • 程序引擎:游戏引擎。解决底层渲染、游戏世界、跨平台等底层问题。
  1. 软件架构的关键目标:

解决:定义做什么!由下层决定怎么做。低抽象编程 关注 怎么做高级抽象编程 关注 做什么思考“做什么”帮助你更好的组织“怎么做”

最小化在编写代码前需要了解的信息/最小化将来需要修改时将影响的范围。代价1:每次改动都要保持它的结构。代价2:基于对未来需求的预测进行的解耦和抽象,存在风险,很可能增加了一堆脚手架仍然没有办法解决未来的需求。代价3:性能的损伤。一种折中的办法是保持代码灵活直到确定设计,再去除抽象层来提高性能。

横向按层分工,有利于改进流程,减少重复劳动成本。纵向功能分工,减少沟通成本。横向按职能+纵向按领域划分vs纵向按公共(相同)/专用划分。业务vs巧合。所有的“公共”都是暂时的。

  1. 根据层次目标的手段:

划分依据:逻辑+视图,业务+通用,数据+显示实现形式:类持有、接口持有、消息传递

源代码       代码           数据宏 <            函数      < 数据宏 < 类 < 接口 < 函数/委托  < 数据

解耦-组织手段:数据、函数、接口、类;面向对象-》面向数据-》面向领域控制权反转,依赖注入(胶水层)actor模式

(代价:用数据代替函数调用,解藕的代价是编辑器不能帮你检查数据完整性,或许需要一个消息检查逻辑帮助检查)

#二、 实现

MVC

MVP

MVVM

View:业务数据无关的通用UI组件: 确保基本组件空值的安全性。 确保 场景编辑的不同,不会。 负责 信息-》显示。Adpater:ViewModel/model组件: 负责设计。负责 模型-》信息——》各组件,负责从模型提取必要的信息,并把信息分配给各UI组件。Controller:

游戏业务的抽象层次:

  • 动作-事件-规则
  • 游戏=规则的组合;规则=概念+逻辑。
  • 问题&解决: 感觉游戏结果模型有各种各样的情况,不好抽象成统一的模型。=》用事实作为模型,各种规则情况不过是针对牌局结果的事实施加不同的逻辑而得出的结果。=》于是可以得出比分、出完顺序、胡等几种基本的数据模型。

三种结构(消息驱动机制):

  • 信赖型控制
    • 基于服务器消息的MVC
    • 通信层–event–控制层–event–视图层
  • 导盲型控制
    • 性能优化的MVVM
    • 控制层–vm–视图层
    • 极端情况下,每个VM都带着完整的顶部Model
  • 裁判型控制
    • 借鉴MVVM的MVC结构(MVC+VM)
    • 控制层–m–业务映射层–vm–视图组件层
    • ModelController–(Model)–ModelView–(ViewModel)–View
    • 关注点拆分:
      • 控制层关注业务M
      • 映射层关注设计VM
      • 组件层关注效果V
    • 优点
      • 更改“设计”时,只需挂载/扩展相应的组件,调整模型view对模型解析的逻辑即可。
      • 多个视图联动时,可在模型view中方便调整节奏。
      • 需要拖拽的信息基本都保存在场景中。prefab仅用于UI/场景组件的使用。
      • 进一步解耦视图层和控制层。
    • 通用的视图组件及其接口!
      • //UINode:UI节点的显示抽象,可替换制定资源by挂载需替换的元素,有统一的显示调用by挂载动画效果。
      • //视图部分的逻辑,很容易把效果逻辑和控制逻辑混淆,效果逻辑可以用通用的效果组件代替,而控制逻辑则对应浇水层的设计粘合。效果逻辑应该仅存在于视图组件中,控制逻辑应该薄薄的存在于胶水层或者隐藏于视图框架中。
      • //问题:为了实现类似但不同的效果,必须重写类似但不同的代码?

两种场景:

  • 纯UI场景
    • //ViewsManager更适合强业务的场景。强UI的场景的话,各视图之间隔离特性就会引发不好联动的问题。这时候可能需要:更换一个互访问更友好的框架,或者引入一个可以统一管理各UI的管理器。
  • 游戏场景

#三、MVVM目前存在的问题:

目前不具备新建能力。考虑View创建过程与View场景编辑的结合。一些情况下控制层关心视图的建立和消失,其他情况下控制层只关心视图的变化。

id、索引的缺失,导致多个view之间的冲突。解决视图冲突问题:一套严格的模型定义系统,或者一套通用的id过滤系统!* 多个接收者时,如何精确定位。* //再分层来解决。概念清晰,语义唯一,不会出现一个模型可以对应多个视图的尴尬情况(气泡模型=>游戏气泡/聊天气泡=>游戏信息模型/聊天信息模型+气泡视图)(倒计时。。。)。以及多个同质的视图模型(各种个人信息面板)* //视图分层解决一对多的反思:一个模型对应多个视图的问题本质在于,语义唯一不能保证视图ID唯一。因此其本质是消息分发的唯一性问题。

VM的语义的完整性?[0,1~N][忽略][全部] //空数组表示没有实际的牌移动,NULL表示所有的牌。

view隔离性强后,移植某块功能,需要涉及多个小视图~需寻找方便的移植方法。以及,view的创建依赖隐性的先验的场景预设。是否可以考虑动态生成?

  • 时间维度的控制问题。
    • //视图层需要控制不同视图同时更新时,动画的播放顺序。比如等上一个动画播完了再更新下一个界面。视图空间上容易解耦,时间上解耦还需考虑)=》后置阻塞、前置阻塞。
    • //时间的含义从严格的动画时间,转变为集成所需的阻塞时间,按需配置。

#九、mvvm与ecs

面向对象的系统抽象过程:针对控制流,划分对象以及方法,面向实体。ECS的系统抽象过程,针对数据流,划分组件数据&系统方法,面向组件。

原文:大专栏  Mvvm In Unity


01-26 22:22
查看更多