# 快速引用

gameplay的基础类库包含展示玩家,盟友和敌人的工具函数,也包括用玩家输入或AI逻辑来控制这些替身。还有些类是给玩家创建屏幕显示和摄像机的。最后像GameMode,GameState和PlayerState这样的类用来设置游戏的规则,然后记录游戏和玩家的运行过程。这些类都可以创建各种类型的Actors,它们会被放到关卡或者在需要的时候生成出来。

# 在世界中代表玩家,朋友和敌人的类

对象 描述
Pawn 一个Pawn可以看成是在游戏世界中的代理Actor。Pawns会被Controller支配,它们很容易地被建立起来用来接收输入,然后做像玩家做的各式各样的事情。注意一个Pawn不是一定被认为是类人形的。
Character 一个Character是类人形的,它有一个CapsuleComponent组件来处理碰撞,有一个CharacterMovementComponent组件用来移动,它能像人类一样移动,并且把这些这些移动状态复制到网络上,还有一些动画相关的工具函数。

# Pawn

Pawn类是所有能被玩家或AI控制的Actors的基类,Pawn是玩家或AI实体在游戏世界中的物理代表。这不仅意味着Pawn决定了玩家或AI实体从视觉上看起来像啥,也决定了它是如何使用Collision和Physical同世界交互的。

这在某些情况下可能会让人有点迷惑,玩家可能没有一个可视化的玩家Mesh或替身,不管怎样,Pawn还是代表了游戏中玩家或实体的location,rotation等等。一个Character是一种特殊的Pawn,它能到处走动。

默认地,Controller和Pawn之间的关系是一对一的关系,这意味着,每个控制器在任意时间只控制一个Pawn。同样地,在游戏中自动生成的Pawn不会被Controller自动拥有。

在蓝图中,最好移动Pawn类的方式是使用SetActorLocation,通过这个函数,你可以决定传送或移动到某个位置,在移动过程中,Pawn会按着方向移动,在碰到东西时会停止。

# DefaultPawn

在Pawn类只提供创建世界中玩家物理代表以及AI实体的基本元素时,DefaultPawn子类提供了额外的组件和函数。它包含一个原生DefaultPawnMovementComponent,一个球形的CollisionComponent和一个StaticMeshComponent。为了控制DefaultPawnMovementComponent以及摄像机,在DefaultPawn类中有一个布尔值来添加默认移动绑定,默认被设置为true。

# DefaultPawnMovementComponent

DefaultPawnMovementComponent移动风格是没有重力,以飞行的方式控制摄像机。除了默认的MovementComponent变量,它包括MaxSpeed,Acceleration和Deceleration,这三个变量在继承DefaultPawn的蓝图中也可以获取。

# SpectatorPawn

这个类是DefaultPawn的子类,通过GameMode,不同的类可被设置为Pawn和SpectatorPawn的默认值,这个类提供了一个简单框架来方便旁观,像DefaultPawn,他有一个球形CollisionComponent,尽管StaticMeshComponent由于.DoNotCreateDefaultSubobject(Super::MeshComponentName)的实现不会被创建,SpectatorPawn类的移动是在SpectatorPawnMovementComponent中处理的,没有重力的飞行行为同DefaultPawnMovementComponent一样,它还有一些处理时间快慢的代码。

# Character

使用CharacterMovementComponent,CapsuleComponent和SkeletalMeshComponent组件,Pawn类会被扩展地特别像Character类,Character是根据玩家在世界中的走,跑,跳,飞,游泳等设计的,这个类还实现了基本的网络和本地输入控制模型。

# SkeletalMeshComponent

不像Pawns,Characters通过SkeletalMeshComponent使用骨架来做动画。这让其他Skeletal Meshes(骨骼网格)有能力来被添加到继承自Character类,但这主要是Skeletal Mesh同Character的事情,要了解这些请看:

# CapsuleComponent

CapsuleComponent被用来处理移动时的碰撞,为了能计算CharacterMovementComponent组件的复杂几何体,我们都默认Character类是胶囊体,要查看更多相关内容请看:

# CharacterMovementComponent

这个组件允许替身不使用刚体来走路,跑步,跳跃,飞,掉落,游泳。它只和Characters相关,不能被任何其他类替代实现。在这个组件中可以改变一些变量,比如掉落,走路摩擦力,在飞行时、水里以及地上的速度,浮力,重力,作用于其他刚体的力。CharacterMovementComponent也包括动画以及由世界转变的根运动参数。

# 用玩家输入或AI来控制Pawn

对象 描述
Controller 控制器是用来直接控制Pawn的Actor,它有两个子类,AIController和PlayerController,一个控制器能拥有一个Pawn,并控制它。
PlayerController 它是在Pawn和玩家控制之间的接口,控制器本质上是代表人类玩家的意志。
AIController 一个AIController主要写如何控制Pawn的AI逻辑。

控制器是非实体的Actors,能拥有一个Pawn(或继承Pawn的类,比如Character)并控制它的行为。人类玩家会使用PlayerController来控制相应的Pawn,同时AI使用AIController来控制AI拥有的Pawn。控制器会使用Possess函数来取得Pawn的控制权,使用Unpossess函数放弃Pawn的控制权。

控制器会接收很多它们所控制Pawn的很多事件通知,这让控制器有机会实现应对某事件的行为,拦截事件,修改Pawn的默认行为。我们可以在Pawn生成之前让Controller开始Tick,这能最大程度地减小从输入处理到Pawn移动之间的延迟。

Pawn和Controller之间的对应关系默认是一对一的关系,这意味着每个控制器在某个时间只控制一个Pawn,这对于很多类型的游戏是可接受的,但是对于某些即时战略的游戏还是需要调整,因为他们需要一次控制很多实体。

# AIController

PlayerController是依赖人类玩家的决策,AIController更多聚焦的是如何应对环境和游戏世界的输入,AIController的任务是监测周围环境并做出反应,它们的行为并不是直接由玩家的输入来决定的。

# PlayerController

PlayerController是玩家控制和Pawn之间的接口,它代表了玩家的意志。要建立PlayerController就需要知道PlayerController里面应该有啥,Pawn里面应该有啥。我们是可以在Pawn里面处理全部的输入,尤其是在一些不复杂的场景里。但是,如果你有更复杂的需求,比如一个游戏客户端里的多个玩家,或者想在运行时改变角色,这时在PlayerController中处理输入会更好,在这种情况下,PlayerController决定了做什么以及同Pawn相关的指令。

同样,在某些情况中,在PlayerController中处理输入或其它函数也很必要,因为它贯穿了整个游戏,相对比之下,Pawn声明周期比较短暂,比如在一个看杀死多少人的比赛中,你可能会死然后重生,所以你会得到一个新Pawn但是你的PlayerController一直保持不变,在这个例子里,如果你在Pawn上存储分数,分数在死亡后就会重置,而在PlayerController里却不会有这个问题。

# 给玩家显示信息

对象 描述
HUD 一个HUD是屏幕信息展示,比如健康值,弹药,枪准星等等,每个PlayerController都会有其中的一些值需要显示。
Camera PlayerCameraController是玩家的眼球,并控制如何表现,每个PlayerController都会有一个。

# Camera

Camera代表了玩家的视口,定义了玩家如何看游戏世界,因此Camera只是相对于人类控制的东西相关的。PlayerController指定了一个camera类并实例化了一个Camera Actor,用来计算玩家在游戏世界中视口的位置和方向。

# CameraComponent和CameraActor

摄像机所有的属性和行为都是在CameraComponent中创建的,CameraActor类包装了CameraComponent,所以camera能不用在附着在其他物体上而直接被放到关卡。

在CameraComponent中,它可以设置是正交模式还是透视模式,在透视模式中可以设置水平角度,在正交模式可以设置宽度,对于这两个模式,都可以设置等比长宽。Post Process effect也被添加到摄像机上,可以用来设置post process effects的强度。

两个组件被添加到CameraComponent来帮助在编辑器中的位置摆放,它们在游戏中是不会被看到的,FrustumComponent展示了摄像机的视野区域,默认是不会开启的,可以在Show > Advanced > Camera Frustums中选择Viewport来开启,StaticMeshComponent则展示了摄像机在关卡中的摆放位置。

# PlayerCameraManager

这个类是camera的管理器,默认它自己内置行为就是协调正常要观察的视口和命令行触发的调试摄像机。否则它需要将要做的ViewTarget设置为摄像机的视角,以及其他摄像机的设置,正常情况下你不需要一个PlayerCameraManager子类除非你需要做些小的改变来添加额外的规则。

你可以使用C++或蓝图来继承PlayerCameraManager,BlueprintUpdateCamera允许定制摄像机的某些实现,在使用这个函数时,返回true来使用返回值,返回false会忽略。

# ViewTarget

在PlayerCameraManager中定义的ViewTarget结构,负责给PlayerCameraManager提供一个理想的Point Of View(POV)。ViewTarget包含目标Actor,目标Actor的控制器(不是本地控制的Pawn)和PlayerState,用来旁观同样player。使用FMinimalViewInfo结构体通过PlayerCameraManager的POV属性传输摄像机信息,这个结构体包含了CameraComponent的基本摄像机信息,包括location,rotation,projection mode(Perspective or Orthographic),FOV,等等,把这些值提供给PlayerCameraManager能让它管理两个摄像机。

# Camera相关

游戏相关的摄像机行为能在摄像机"责任链"的任何时候被提供,可从上到下来通过下面的类传给ALocalPlayer以及渲染,场景视图和其他相关系统。

# CameraComponent

如果ViewTarget是一个摄像机Actor或者拥有CameraComponent组件的Actor,并且bFindCameraComponentWhenViewTarget设置为True,那么CameraComponent就能提供摄像机的相关属性。任何Pawn都可以设置的一个布尔变量是bTakeCameraControlWhenPossessed,它能让PlayerController在拥有Pawn的时候让这个Pawn自动成为ViewTarget。

# Actor和PlayerController

PlayerController和Actor都包含一个CalcCamera函数,如果bFindCameraComponentWhenViewTarget被设置为True并且有CameraComponent,一个Actor的CalcCamera函数会返回Actor的第一个CameraComponent的摄像机视角。否则它会得到Actor的location以及rotation。在PlayerController中,CalcCamera在第二种场景下表现都会差不多,会返回Pawn的location以及PlayerController的控制rotation。

# PlayerCameraManager

它里面的UpdateViewTarget函数会查询ViewTarget然后返回ViewTarget的POV,如果你有一个APlayerCameraManager子类并且没有通过CameraComponent的时候,这个函数也会调用BlueprintUpdateCamera。

# CameraAnims

从概念上讲,CameraAnim只是被添加到游戏中Camera的一段动画,你可以设置摄像机的location,rotation,FOV,post process setting。一个CameraAnim的position,rotation,FOV的改变会被额外的添加到游戏的摄像机中,这些关键帧是"相对于初始化的",这意味着从0.0开始动画开始被使用。

CameraAnim的后期处理设置以一种混合/层叠的方式被使用,像其他影响场景的后期处理的系统一样,你可以选择你想要重写摄像机的属性然后通过Matinee轨道来调整,Matinee被弃用后现在就是Camera Animation Sequence,可以在预览窗口看这段动画,临时的摄像机也有PostProcessBlendWeight属性,通过它你可以控制你的设置影响场景的强度。

# 设置游戏的规则

对象 描述
GameMode 游戏的概念被分成两个:GameMode和GameState,GameMode包括游戏规则和胜利条件,并且只存在于服务器上,它不应该包含很多游戏中会变的数据,包括很多客户端应该知道的短暂数据。
GameState GameState包含了游戏的状态,它包含连接玩家的列表,分数,你在开放世界中已完成的列表。GameState存在于服务器和所有客户端里,它能自由地复制并让所有机器一直保持是最新数据。
PlayerState 一个PlayerState是参与者的状态,比如人形玩家或者模拟玩家的机器。非玩家的AI会作为游戏的一部分,它们并没有PlayerState,在PlayerState中合适存放的数据包含玩家姓名,分数,像moba的匹配关卡,或者在CTF游戏中玩家是否在扛旗。PlayerState存在于所有的机器上,不像PlayerController,能自由地复制并保证同步。

# 框架类之间的关系

下面的流程图阐释了gameplay的核心类是如何相关联的。一个游戏是由GameMode和GameState组成,玩家加入游戏会有PlayerController关联,这些PlayerController允许玩家在游戏中拥有一个物理上的代表Pawn。PlayerController也让玩家有输入控制,屏幕显示或HUD,PlayerCameraManager用来控制摄像机视角。

GameplayFlow