一直说自己是Gameplay程序员,那么今天来谈一下Gameplay,尤其是UE4的Gameplay。
Gameplay就是使得游戏好玩的游戏交互。好玩是个很抽象的概念,但是游戏的操作手感,游戏设计,输入等,都可以算到好玩不好玩上。于是就有了Gameplay的3C概念,也就是Character、Camera、Control。此外,Gameplay还需要处理游戏环境的东西,可交互物体,碰撞物体,静态网格啥的。
这里列出一些常见的Gameplay系统做例子
Character表现游戏世界中的玩家,Character一般拥有游戏世界中最复杂的行为,对于程序员来说,要负责处理角色的移动,动画,皮肤(装备)等。
// 假如实现炸弹人中的角色
class Character
{
public:
Character();
virtual ~Character();
virtual void Move(Direction dir);
virtual void PlaceBomb();
virtual void DoCollision(Item item);
virtual void Update(float deltaTime);
virtual void render();
protected:
Controller* m_Controller;
}
Camera处理游戏视角,表现游戏世界,第一人称,第三人称,FOV,VFX,后处理,抖动等。摄像机也是重要组成,一个游戏如果摄像机没有处理好,会引起玩家游玩时的不适感。
处理输入(来自鼠标键盘,手柄,模拟器等,以及输入模式例如单击、按住、双击),匹配输入逻辑(按键映射),处理回应输入的逻辑,UI交互,以及物理模拟,AI驱动。
我们使用游戏脚本(Game Script)为游戏添加独立模块。
脚本使用脚本语言编写。脚本语言是用来给一个或多个应用程序做控制的编程语言。脚本语言给程序开发新功能更方便,但是却没有程序的原生语言运行速度快。
脚本语言可以做如下分类,这个算小科普:
计算机程序是操作系统把机器码提取到内存中并执行的,而脚本需要在主程序为其提供的虚拟机(Virtual Machine)环境下运行。对于脚本系统,有三个基本类型:程序的/面向对象的语言系统、基于命令行的语言系统、动态链接模块系统。
UE4提供了一个十分完整的Gameplay框架,能满足基本上所有Gameplay功能的实现,所以在使用UE4实现某个Gameplay功能时可以先找找UE4有没有这样的框架,不用白不用。如果有的话,我们只需要在框架的基础上进行修改就行,从UE4提供的类作为基类创建自己的子类,就是一种运用办法。
注意,虽然UE4源代码开源,也尽量不要直接修改引擎代码。因为一旦更新你的修改就没了,而且改引擎代码常常出现各种奇奇怪怪的BUG产生。
UE4的游戏世界构成层级为:
各个重要的游戏框架类,认识一下对于今后的代码逻辑书写有帮助
Actor类继承自UObject类,UObject类的主要功能是弥补一些C++没有,但是有些引擎需要的功能,比如GC、反射机制、序列化、MetaData、Editable、Class Default Object。可以将Actor类比为Unity中的GameObject,是游戏逻辑中的主要元素。
Actor除了继承自UObject的功能外,自己还实现了一个AActor指针类型的TArray和一个指向Owner的AActor*用来实现嵌套,以及会在游戏的每一帧都调用的Tick函数用于游戏逻辑更新(类比Unity里的Update),Spawn,以及网络复制。
虽然说,一切放在场景中的对象都是Actor,有些表示状态,规则的信息类(如AInfo)也可以是Actor,这些Actor不一定要放到游戏世界中。所以更严谨一点的说法,加装了SceneComponent(类比Unity中的Transform)作为RootComponent的Actor可以放到游戏场景中。
Actor类中还有很多重要子类,比如
类似于Unity中的Component(说不定就是从那里学的),作为一种可复用的功能接口用于给不同的Actor提供某项功能,Component可以附加给一个Actor,这样该Actor就拥有了这个Component提供的功能。
如果没有Component,按照UE4的逻辑,任何Actor要实现一个新功能都需要创建一个子Actor来实现,功能一多就会创建一大堆臃肿的Actor类,而如果将那些可复用的功能写到Component中并将Component与需要该功能的Actor组装起来,就不再需要为该Actor创建Actor子类了。
Component的基类是UActorComponent,也是继承自UObject,拥有UObject的特性。在Actor中会有一个表OwnedComponents来指向该Actor拥有的所有Component。
GameMode类定义游戏规则,存在于每个World/Level中,并且只在服务器上,通过GameState来传递(transfer)信息。
管理世界切换,玩家、UI的加载,控制台命令和额外的逻辑,初始化/关闭引擎,创建玩家,修改GameMode,在线会话管理。总之就是掌管一些全局性的东西。
UPlayer更多的使用在多人游戏的场景,管理控制器的连接,生成玩家控制器(PlayerController)和玩家状态(CurrentNetSpeed啥的)。继承自UObject。联网游戏还会在每个游戏实例生成LocalPlayer类的实例,但是现阶段官方隐藏了LocalPlayer的接口,不建议使用。