2 - 游戏模式
腾讯2024游戏客户端公开课笔记,UE的游戏模式部分。
游戏模式
概念
游戏模式就是 在游戏世界里组织数据和运作规则的方式,例如决定游戏玩家数、决定游戏是否允许暂停、设置游戏暂停时的处理等。
UE游戏模式框架
万物之源 UObject
如图,UObject类是UE框架的万物之源,它赋予自身和子类各种各样的功能,包括元数据、反射生成、GC、序列化等。此外也提供了一些通用的属性和接口。
物体的表达 Actor + ActorComponent
UE使用EC架构(Entity-Component Framework)来表达一个物体,通过给物体(Actor)附加多种组件(Component),来让它拥有相应的能力。例如SceneComponent就包含了这个物体的3D变换信息。
世界的表达 UWorld + ULevel
UE用UWorld来表达游戏世界,包括实际游戏中的GameWorld,编辑器中的PIEWorld,Debug预览用的PreviewWorld等。UWorld类中又包含若干关卡ULevel,通常是一个主关卡PersistentLevel和若干子关卡SubLevel。
UE使用LevelStreaming技术来流式异步加载关卡,关卡加载的逻辑主要有下面3种:
UE5新增的WorldPartition;
WorldComposition:
LoadByLogic;
为了加快加载效率以及避免消耗非必要资源,可以通过 “LevelBounds + StreamingDistance分层” 技术来设置关卡大小和加载距离。
此外,还能通过 关卡蓝图 LevelScriptActor 来定义关卡的规则。
世界之上 UGameInstance + UEngine
管理世界和关卡的是UGameInstance类和UEngine类,它俩的职责如下:
- UGameInstance负责管理世界和关卡,它的信息存在于整个游戏的生命周期,不随着地图的切换而销毁。它非常适合管理全局的非业务逻辑,例如全局的UI、设置、一些预加载等。
- UEngine则负责管理UGameInstance,它通过一些方法来管理游戏中重要的流程,例如地图加载等。
UE游戏世界的加载流程如下:
- UGameEngine::Init:设置并创建本地玩家;
- UGameEngine::start:开始游戏实例UGameInstance,同时让UEngine加载世界。
- UEngine::LoadMap:首先通过LoadPackage让UWorld和ULevel进行后加载,然后开始设置游戏实例并初始化世界,接着进行游戏模式的设置和关卡流式加载,最后初始化供游玩的Actor,以及初始化玩家的Actor。
游戏模式中的重要对象
AActor
基础概念
AActor类是游戏中最重要的实体,它提供了许多功能:
- OwnedComponents:各种组件为Actor提供对应功能。
- RootComponent:根组件提供世界变化信息。
- Children:为子Actor提供附着功能,例如玩家受伤的枪。
- 网络同步组件:AActor是网络同步的基础单位,拥有 Owner指针,本地权限Role枚举以及一些网络同步和实例化组件。
生命周期
一个Actor的生命周期如下:
首先需要加载Actor,Actor可被分为两类:
关卡内摆放的静态Actor:在上图的左半边,黄色/深蓝色部分。
通过SpawnActor创建的动态Actor:
- 本地Spawn加载
- 网络序列化加载
在上图的右半边,浅蓝/橙色部分。
接下来开始执行 BeginPlay() 函数,它表示一个Actor开始的生命周期,可以在这里获取和设置它的相关参数。
在Actor的运行期间,会在引擎的每一Tick执行 Tick() 函数,执行并更新相关信息,比如渲染逻辑和物理逻辑等。
如果游戏场景中不再需要这个Actor,则会执行 EndPlay() 函数,可以在这里写一些Actor结束时的逻辑。
最后,该Actor会被标记为待销毁,然后交由GC进行销毁。因此在判断一个Actor是否合法(IsValid)时,除了判断它是否在内存中存在,还要看它是否被标记为待销毁。
APawn
基础概念
APawn类继承AActor类,它表示游戏中可被操控的对象,例如人物、载具等。在Actor的基础上,可通过Controller来控制Pawn,支持一些基础的输入和移动框架。
派生类
APawn还有一些常用的派生类:
- ADefaultPawn:这是UE提供的简单默认Pawn,它提供了简单球形碰撞组件 USphereComponent、简单外部显示组件 UStaticMeshComponent、简单移动组件 UFloatingPawnMovement,以及基础的输入映射(键盘、手柄);
- ASpectatorPawn:适用于游戏中的观察者模式,去掉外部显示组件,将移动组件替换为忽略时间缩放的 USpectatorPawnMovement。
- ACharacter:将在下文详细介绍。
ACharacter
基础概念
继承自APawn,更适合用于人形角色的控制,在APawn的基础上,ACharacter类拥有:
- 近似人形的胶囊体碰撞盒 UCapsuleComponent:在保证一定真实性的同时,节约性能。
- 骨骼模型 USkeletalMeshComponent:动画蓝图 + 人物骨骼赋予人物生动表现。
- 人物移动组件 UCharacterMovementComponent:它配合胶囊体组件完成如走路、掉落、游泳、飞行等多种仿真移动计算;还提供Custom移动模式让开发者自定义移动;并且提供了网络游戏的移动同步功能。
AController
基础概念
可以控制Pawn,Controller通过 Possess(APawn*)
方法来控制Pawn;Pawn通过 PossessedBy(AController*)
接受Controller的控制。AController下还有APlayerController和AAIController,将在下文介绍。
APlayerController
专门给玩家用的Controller,通过UInputComponent绑定输入映射,通过APlayerCameraManager来计算相机位置;通过AHUD来展示控制相关UI,但逐渐被更灵活的UMG取代;此外还有网络连接的所有权(主控端和服务器)。
PlayerController类可以视为代表玩家的实体,其本质上是Pawn的核心。它接受来自用户的输入,并将其传递给Pawn和其他类,以便玩家与游戏进行交互。在处理该类时必须注意以下几点:
- 与Pawn类不同,在一个关卡中只能有一个PlayerController代表玩家。
- PlayerController类在整个游戏中持续存在,但Pawn类可能不会(例如人物死亡后会重生,但它的Controller不会变)。正因如此,开发者需要记住应该将哪些代码添加到哪个类中。
AAIController
专门给AI用的Controller,让AI的行为树自行决策所控制Pawn的行动。少了例如玩家输入、相机等组件,多了用于寻路的Navigation组件、AI组件、任务Task组件。
AGameMode
基础概念
仅服务器拥有,定义游戏模式用的基础类型,掌握整体游戏流程。AGameModeBase是所有GameMode的基类,是经典AGameMode(UE4.14前)的简化版本。现在的AGameMode是AGameModeBase的子类,它更适用于标准对抗类游戏(如多人射击类),完善了对局和比赛的概念。
AGameState
所有端都共享同步的游戏状态数据,例如团队的分数、目标,还有玩家列表及其PlayerState。
APlayerState
所有端都共享同步的玩家自身状态数据,例如血量、子弹量、物品栏。
参考资料
- InsideUE5 - 知乎 (zhihu.com)