UE4 GamePlay框架学习

学习资料:https://zhuanlan.zhihu.com/p/22813908

新手上路,还需指正

 


GamePlay架构(一)Actor和Component

万物皆UObject:元数据、反射生成、GC垃圾回收、序列化、编辑器可见,Class Default Object

Actor继承了UObject,有了Replication(网络复制),Tick,Spawn(生成)。其实Actor只是一个概念上的东西,通过添加组件使得其显形在UE4世界中。

正因为如此,Actor并不会自带Transform,浪费内存空间,UE4的Bool都会用位域去尽可能利用空间。UE4将Transform封装进了SceneComponent。大部分的Actor的(GET/SET)ActorLocation是一个封装好的函数,内部实现是先去寻找RootComponent.

Actor通过组装Component武装自己的功能

Actor和Actor之间的父子关系本质是通过SceneComponent实现的(AttachToActor/AttachToComponent)

总结一下:Actor其实就是灵体,通过添加组件使得现形在世界场景中,Actor和Actor之间的父子关系是通过AttachToActor,Actor和组件是直接AttachToComponent,最终都是通过RootComponent去实现父子关系。


GamePlay架构(二)Level和World

一个World支持一个PersistentLevel,对应有多个Level,Level自带一个ALevelScriptActor(关卡蓝图),可以在关卡中通过名字获取Actor。一个Level对于一个AWorldSetting(书记官)。一个Level有多个Actors。

通过关卡流,可以构建庞大的开放世界。但每个Level有唯一的GameMode,通过关卡流加载关卡后,以哪个关卡为主?其实是以当前关卡为主

总结:Level是Actor的容器,同时划分了World


GamePlay架构(三)WorldContext,GameInstance,Engine

WorldContext负责控制World之间的切换,也负责level的切换

 

有一个平行世界的概念,GAME模式和编辑器模式

思考:为何Level的切换信息不放在World里? 
因为UE有一个逻辑,一个World只有一个PersistentLevel(见上篇),而当我们OpenLevel一个PersistentLevel的时候,实际上引擎做的是先释放掉当前的World,然后再创建个新的World。所以如果我们把下一个Level的信息放在当前的World中,就不得不在释放当前World前又拷贝回来一遍了。 
而LoadStreamLevel的时候,就只是在当前的World中载入对象了,所以其实就没有这个限制了。

GameInstance是比WorldContext更高一级的类,不管Level如何切换,都不影响里面的数据

 

Engine比Instance更高一级

StandLone Game:使用UGameEngine创建出唯一的World,因此直接用GameInstance保存

而对于编辑器来说,EditorWorld其实只是用来预览,所以并不拥有OwningGameInstance,而PlayWorld里的OwningGameInstance才是间接保存了GameInstance。因为UE4只允许一个World运行,因此GameInstance也是唯一的

总结:Object→Actor+Component→Level→World→WorldContext→GameInstance→Engine。至此,完成了所有“数据”,接下来讨论具体的游戏逻辑如何布局


GamePlay架构(四)Pawn

Actor是由Component组成的一个个功能,真正的Component应该是可以无痛处的转移到另一个项目,不参杂任何游戏逻辑

因为UE4是FPS起家,一个Pawn是棋子士兵,(和战场上的士兵类似)其能够移动,有物理碰撞,可以响应输入和处理逻辑(Controller),Pawn拥有能力。Pawn就是木偶,Controller是提线人


GamePlay架构(五)Controller

MVC

controller的作用是为游戏编写逻辑,controller和player的关系是1:1;controller调用pawn的方法。如果是一些Pawn本身固有的能力逻辑,如前进后退、播放动画、碰撞检测之类的就完全可以在Pawn内实现;而对于一些可替换的逻辑,或者智能决策的,就应该归Controller管辖。即个性的功能逻辑可以写在Pawn里,通性的可以写在Controller里

controller有两个子类PlayerController(响应玩家输入,处理游戏逻辑)和AIController(用行为树)

controller有场景组件,意义在于ReSpawn的时候可以指定为它的位置,一般是概念上的位置

Info有两个子类是PlayerState(保存玩家在Level的状态,往往Controller里会有这个变量,但AI不会有)和GameState

UE这里其实想说的是,这些更新位置的操作还是让我来为你管理吧,我真的担心你会用错搞出什么乱子来。顺便再说些题外话,对于PlayerController来说,因为玩家需要一个视角来观察世界,所以常常PlayerController常常会扛着个摄像机出现(蓝图里没有,但是会运行时生成PlayerCameraManager和CameraActor),所以就算没有角色可供操作,玩家也依然希望是可以视角漫游观察整个世界的(试试看把默认Level里的PlayerStart删掉后运行看看)。这个时候PlayerController常常会默认创建出一个ASpectatorPawn或者DefaultPawn(根据GameMode里配置),我们虽然看不见Pawn,但依然可以观察世界,靠得就是跟Controller关联的旋转和摄像机。

其实是Actor(AController)对Actor(APawn)的控制


GamePlay架构(六)PlayerController和AIController

一个时刻只有一个PlayerController能够响应

M(PlayerState) V(View,UI) C(Controller)


GamePlay架构(七)GameMode和GameState

GameMode关注于当前世界的游戏规则,负责调度这个世界。

level里的gamemode是强制的,如果为空,就用project setting里的gamemode


GamePlay架构(八)Player

UPlayer有一个PC,UPlayer保存在Instance里

ULocalPlayer继承自UPlayer,关联着输出,多了个ViewPort

玩家是游戏数据的发起者,那么网络远端把数据传过来的也是玩家,所以UNetConnect也继承自UPlayer


GamePlay架构(九)GameInstance

切换关卡,生成Player

SaveGame存档


GamePlay架构(十)总结

https://zhuanlan.zhihu.com/p/24170697/

UE4,万物皆Actor,Actor再通过Component组装功能。Actor又通过UChildActorComponent实现Actor之间的父子嵌套

众多的Actor构成level,一个个level组成了World:

而World之间的切换,UE用了一个WorldContext来保存切换的过程信息。玩家在切换PersistentLevel的时候,实际上就相当于切换了一个World因为UE有一个逻辑,一个World只有一个PersistentLevel(见上篇),而当我们OpenLevel一个PersistentLevel的时候,实际上引擎做的是先释放掉当前的World,然后再创建个新的World。

preview

GamePlay框架使用了MVC架构,Pawn视图,PlayerState数据,PlayerController控制器。

一个游戏由游戏规则(GameMode)和游戏状态组成(GameState);玩家是Pawn,通过PlayerConroller控制,通过PlayerCameraManager观察世界,PlayerState记录玩家数据,HUD显示数据内容;NPC由AIConroller去控制,和玩家进行互动。
 

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值