当前位置: 首页 > 工具软件 > Gameplay > 使用案例 >

谈谈Gameplay,以及UE4的Gameplay框架

苏鸿羽
2023-12-01

前言

一直说自己是Gameplay程序员,那么今天来谈一下Gameplay,尤其是UE4的Gameplay。

什么是Gameplay

Gameplay就是使得游戏好玩的游戏交互。好玩是个很抽象的概念,但是游戏的操作手感,游戏设计,输入等,都可以算到好玩不好玩上。于是就有了Gameplay的3C概念,也就是Character、Camera、Control。此外,Gameplay还需要处理游戏环境的东西,可交互物体,碰撞物体,静态网格啥的。

这里列出一些常见的Gameplay系统做例子

  • 战斗系统
  • 角色成长系统
  • 自定义移动/动画/摄像机以及其它自定义系统

Character

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

Camera处理游戏视角,表现游戏世界,第一人称,第三人称,FOV,VFX,后处理,抖动等。摄像机也是重要组成,一个游戏如果摄像机没有处理好,会引起玩家游玩时的不适感。

  • 第一人称摄像机,常用于第一人称射击游戏,要让玩家完全以角色的视角体验游戏。需要将摄像机放到游戏角色头上并向前看,让摄像机随着玩家移动和旋转。
  • 第三人称摄像机,常用于策略游戏,角色扮演游戏,能给予玩家更多的信息。一般把摄像机放在与角色保持一定距离的空间或者策略游戏的固定视角、俯视角、自由视角。第三人称摄像机往往要考虑与3D世界中其它物体的碰撞和遮挡。
  • 有些时候,会使用曲线来控制摄像机,来得到好的摄像机视角,往往运用于电影化游戏和即时演算过场中。

Control

处理输入(来自鼠标键盘,手柄,模拟器等,以及输入模式例如单击、按住、双击),匹配输入逻辑(按键映射),处理回应输入的逻辑,UI交互,以及物理模拟,AI驱动。

游戏脚本

我们使用游戏脚本(Game Script)为游戏添加独立模块。

介绍脚本语言

脚本使用脚本语言编写。脚本语言是用来给一个或多个应用程序做控制的编程语言。脚本语言给程序开发新功能更方便,但是却没有程序的原生语言运行速度快。
脚本语言可以做如下分类,这个算小科普:

  • 作业控制语言(Job control language)和shells(JCL, Unix Shell, Command, AppleScript)
  • 图形界面(GUI)脚本。
  • 应用特定语言(application specific language),好像也叫领域特定语言(Domain Specific Language)
  • 网页前端脚本(HTML, VBScript, JavaScript)
  • 网页后端脚本(服务器)(PHP, JSP, ASP)
  • 文本处理语言(Text processing languages)(Unix’ AWK, sed, grep)
  • 通用动态语言(General-purpose dynamic language)(Perl)
  • 拓展/可嵌入语言(Extension/embeddable language)(Tcl)

脚本系统

计算机程序是操作系统把机器码提取到内存中并执行的,而脚本需要在主程序为其提供的虚拟机(Virtual Machine)环境下运行。对于脚本系统,有三个基本类型:程序的/面向对象的语言系统、基于命令行的语言系统、动态链接模块系统。

UE4 Gameplay框架

UE4提供了一个十分完整的Gameplay框架,能满足基本上所有Gameplay功能的实现,所以在使用UE4实现某个Gameplay功能时可以先找找UE4有没有这样的框架,不用白不用。如果有的话,我们只需要在框架的基础上进行修改就行,从UE4提供的类作为基类创建自己的子类,就是一种运用办法。

注意,虽然UE4源代码开源,也尽量不要直接修改引擎代码。因为一旦更新你的修改就没了,而且改引擎代码常常出现各种奇奇怪怪的BUG产生。
UE4的游戏世界构成层级为:

  1. GameInstance(这是整个游戏实例,由GameEngine创造出来)
  2. World(游戏世界,常用结构体FWorldContext记录了游戏世界的各种信息使用在游戏世界切换等功能)
  3. Level(对于一个游戏世界,可以分成多个Level,比如将游戏场景分成一个Level,灯光分成一个Level等等,这样有利于美术师进行场景搭建,关卡也分为Persistence Level和Streaming Level,Persistence Level可以理解为主Level,我们的世界建立在Persistence Level上,Streaming Level就是前面提到的作为部分内容的Level按照我们定义的规则加载到Persistence Level里的Level)
  4. Actor(所有能放到游戏场景中的对象的基类都是AActor)
  5. Component(表现Actor的各种构成部分,UE4中Component类类似与Unity的Component,能够附加到Actor上)

介绍重要框架类

各个重要的游戏框架类,认识一下对于今后的代码逻辑书写有帮助

Actor类

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类中还有很多重要子类,比如

  • AInfo类
  • APawn类(3C的Character,可操控的Actor)
    • 连接Controller(有一个AController的指针)
    • 物理碰撞(CollisionComponent/CapsuleComponent)
    • 移动输入(ControlInputVector)
  • AController类
    • 连接视线-模型(View-Model)
    • 接受/未接收到输入的处理
    • 通用逻辑,其他Actor也能有的逻辑
  • APlayerCameraManager类
  • AStaticMeshActor类

Component类

类似于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类

GameMode类定义游戏规则,存在于每个World/Level中,并且只在服务器上,通过GameState来传递(transfer)信息。

GameInstance类

管理世界切换,玩家、UI的加载,控制台命令和额外的逻辑,初始化/关闭引擎,创建玩家,修改GameMode,在线会话管理。总之就是掌管一些全局性的东西。

Player类

UPlayer更多的使用在多人游戏的场景,管理控制器的连接,生成玩家控制器(PlayerController)和玩家状态(CurrentNetSpeed啥的)。继承自UObject。联网游戏还会在每个游戏实例生成LocalPlayer类的实例,但是现阶段官方隐藏了LocalPlayer的接口,不建议使用。


 类似资料: