当前位置: 滚动 > >正文

[浅谈UE] 我理解的Unreal MVC模式

来源:哔哩哔哩    时间:2023-04-23 13:49:36

前言

本文仅为本人在使用和研究Unreal的Gameplay框架时的一些思考的分享,如存在错误或不严谨之处望指正。


(资料图)

MVC模式

MVC模式,软件工程中一种常见的设计模式,在前端框架中广泛应用。其大体划分为3个部分:M(Model)、V(View)、C(Controller)

三个部分分别对应三个功能:数据存储(M)、用户交互(View)、逻辑处理(Controller)

三个功能的组合与协作,便可驱动用户与数据的交互。

在Unreal中

在谈到Unreal的MVC模式前,请容许我插入一个小片段,以便更好地理解相关的内容。站在Unreal Engine开发者的角色,我们来尝试理解他们希望创造一个什么样的游戏世界。

一款游戏就是一部戏剧,Actor是演员,Component是演员的道具,Actor们拿着自己的演出道具表演。这正对应着Actor可挂接不同的Component以完成不同的功能。此外,正如大钊老师所说,Actor应该承担业务逻辑,Component应该承担通用功能。Actor仅对当前戏剧服务,卡西莫多这一角色只能出现在《巴黎圣母院》中,而吉普赛少女的连衣裙可以出现在其他的戏剧中,只是它们被赋予的功能和不同。它可以作为贵族宴会的礼服,也可以作为普通农家少女的便装,它是什么并不重要,它只负责展示出衣服的模样。就如同Component,只是承担通用的功能,也就是说切换到其他项目中也可一定程度进行复用。

举个最简单的例子,UCharacterMovementComponent可以应用在多个游戏中,它提供封装式运动系统,具有人体模型角色的常见移动模式。不管你开发的是第一人称射击游戏还是第三人称动作游戏,角色的移动都可以借助这个组件,因为它提供通用的功能,而非具体的业务逻辑。

Level是,在一幕中Actor们进行着表演,当然一部戏剧可能有很多幕,在不同幕中会有不同的表演,幕与幕间也会有相应的联系。一幕戏总有些统一的规则,所有Actor都遵循着这一个规则,比如说“深夜、大雨、周公馆内”。这正对应的是WorldSettings,虽然叫做WorldSettings,但本质上它是当前Level的通用配置,描述当前Level的规则。

World是这一场完整的戏剧,它将幕和幕之间进行拼接。但是一场戏剧不只是有演出日前的那一次华丽的表演,还有多次的彩排,通过一次次的确认和调整最终给观众一个最为完美的表现。这也正对应着Unreal中各个不同种类的World,在EWorldType::Type中可以查到各个World的Type信息。有的World是最终展现的版本,有的World用于预览。相同的逻辑在各个不同的World之间可能会有很大的出入,毕竟服装彩排、对话彩排、总彩排等彩排形式之间的侧重点有所不同。

如何理解上述描述呢?举一个简单的例子,当我们利用动画通知(AnimNotify)生成了一个碰撞盒,如果我们在场景编辑器下可以将盒体选中并拖拽改变其Transform,但当我们在动画预览编辑器下却无法被选中;再举个例子,当我们利用动画通知生成粒子特效,当我们在动画预览世界点击暂停按钮,特效不会暂停,但在粒子特效编辑器预览世界中我们可以很方便地暂停特效。举以上几个例子的目的是想说明,Unreal的确具有多个World,并且多个World之间的确存在一些差异,就像是彩排之间的不同侧重点,不同World下也有相应的侧重点。(顺便一提,如果要实现上例的功能,可以考虑扩展编辑器,具体可以查阅EdMode相关内容)

现在我们把目光放在那一群Actor中。Actor有很多种类,有的静止不懂,像石头木桩一样作为摆设,与主角几乎无任何戏份,是配角中的配角。在游戏中,它们是些普通的Actor。但是普通的Actor也会有Component,需要放置在场景上就需有SceneComponent,显示模型就需要有MeshComponent等。

我们的主角,他们是戏剧的核心,他们是聚光灯的焦点,他们推动着情节发展。在戏剧中,主角是导演设定的,主角拿着剧本演出着固定的内容。但是在游戏中,读者认为主角是谁呢?我认为就是玩家自己,在屏幕中那个蹦蹦跳跳的角色只是接收玩家意志的傀儡,它受玩家所控制,它接受玩家给予它的剧本。请记住这一点,在过后分析Controller和Pawn的过程中会很有帮助。

当然还有一类就是反派,或是主角的同伴,他们可以和主角交互,自然也会有他们的戏份。那它们和主角的区别是什么呢?答案显而易见,它们不是聚光灯的焦点,但是却需要根据剧本完成演出。仅对于一部戏剧的话这并不困难,因为主角的剧本是固定的,它们的剧本也是固定的,只需要按照固定的剧本来演出即可。可是游戏中主角的行为由玩家决定,玩家的行为千变万化,这就需要配角们根据玩家的行为变化做出相应的响应,这便是Unreal中AI解决的问题。

现在让我们重新回到MVC模式的话题上,我认为有了上述的分析便可更清晰地理解Unreal中的MVC模式。

Pawn是肉体、是提线木偶、是没有剧本的主配角们,不管你是老戏骨还是新人,没有剧本只能在舞台上一动不动,但是本身来讲老戏骨具有更多更强的表演能力,只是暂时还没有人命令他展现出这种能力。

Controller是灵魂、是操控线、是监工,它可以控制Pawn让其发挥相应的能力。那Controller又根据谁的指使发号施令呢?对于玩家,那Controller便听从玩家的指挥,具体来说便是根据玩家的输入执行相关的输入处理。对于NPC,那Controller便根据AI行为树的逻辑来判断执行相应的控制,由此可见行为树一定程度上在模拟玩家的决策。

PlayerState是玩家的数据,记录着玩家的状态。Blackboard是NPC的数据,记录着NPC的状态。

现在MVC的关系便显而易见:Controller作为逻辑层,Pawn作为模型层,Controller根据玩家交互或AI决策控制Pawn执行对应的行为,而PlayerState(Blackboard)作为数据层保存着模型相关的数据信息,以供逻辑层和模型层使用与管理。

再简化

为了更好地理解Unreal的MVC模型,我对Unreal的模型进行了一定的简化。场景仅为2D的控制台,玩家仅用键盘控制角色平面内移动,去除AI、网络等机制,仅专注于玩家的交互、角色的控制、角色的数据和角色的行为,最终我抽象出了一个简易的MVC模型:

https://github.com/itmWUMA/MVC_SimpleModel

相关参考:

InsideUE系列Unreal Engine Documentation《游戏编程模式》Robert Nystrom著相关源代码

X 关闭

精心推荐

Copyright ©  2015-2022 欧洲建筑工程网版权所有  备案号:沪ICP备2022005074号-23   联系邮箱: 58 55 97 3@qq.com