ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

UE5 入门系列(三):核心框架类全解析

UE5 入门系列(三):核心框架类全解析

系列导读

经过前两篇,你已经装好了引擎、创建了项目,也熟悉了编辑器的基本操作。理解 UE 的框架类是入门开发的重中之重,后续写蓝图、写 C++,本质上都是在与这些类打交道。

第一次打开 UE 的文档或源码,很容易被一堆名字吓住:GameMode、GameState、PlayerController、PlayerState、Pawn、Character、HUD……它们长得都差不多,到底有什么区别?

别担心。本篇主要讲解这些类是什么,管什么;在真实场景当中,如何完成一整局游戏的。

读完你会发现,这套框架不是什么死记硬背的知识,而是一套非常自然的"分工设计"。

一、核心框架类什么

在讲任何细节之前,先建立整体印象。UE 的框架类本质上是在回答一个问题:“一局游戏里,都需要哪些角色来分工?”


类一句话定义类比
GameMode定义游戏规则":用什么角色、怎么重生、怎样算赢裁判
GameState存放全局共享的游戏数据(比分、剩余时间),并同步给所有玩家记分牌
PlayerController接收玩家输入(键盘/鼠标),指挥角色行动玩家的大脑
PlayerState记录单个玩家的持久数据(昵称、击杀数、得分)玩家档案
Pawn世界中"被控制的身体",自己不会思考身体
CharacterPawn 的强化版:能走能跳、带骨骼动画的角色有血有肉的身体
AIControllerAI 的大脑,用行为树驱动 Pawn 行动AI 的大脑
HUD / UMG把游戏状态画到屏幕上(血条、准星、比分板)显示屏

再提炼一层,这八个类其实属于四个"层级":

  • 规则层:GameMode(只存在于服务器,负责裁决);
  • 状态层:GameState(全局)、PlayerState(个人),负责"让所有人看到同一份数据";
  • 控制层:PlayerController / AIController(大脑)+ Pawn / Character(身体),负责"行动";
  • 表现层:HUD / UMG,负责"展示"。

这里最主要的:AGameMode、AGameState、APlayerController、APawn/ACharacter、AHUD/UMG

打开任意关卡,在菜单栏进入窗口(Window)→ 世界场景设置(World Settings),右侧面板中可以看到当前关卡使用的游戏框架类:

这里指定的 GameMode,决定了这个关卡"怎么玩"——用什么角色、用什么控制器、死了怎么重生。其他几个类(GameState、PlayerState、HUD 等)通常在 GameMode 内部指定。

类继承图

UObject(所有对象的基类) └── AActor(世界中的实体,可以放进关卡) ├── APawn(可被控制/附身的载体) │ └── ACharacter(带骨骼动画和移动组件的 Pawn,最常用) ├── AController(控制 Pawn 的"大脑",不在关卡中放置) │ ├── APlayerController(玩家控制,处理键盘/鼠标输入) │ └── AAIController(AI 控制,由行为树驱动) ├── AGameModeBase(游戏规则定义者) ├── AGameStateBase(全局游戏状态,同步所有客户端) └── AHUD(平视显示器,绘制 UI)

二、每个类是做什么的

1. AGameMode

核心职责:定义"游戏规则"。包括使用哪个角色、哪个控制器、如何重生、胜利条件是什么。

常用可重写的函数:

函数调用时机典型用途
InitGame()游戏开始时初始化全局数据
PreLogin()/PostLogin()玩家连接前 / 连接后校验玩家、发放初始资源
SpawnDefaultPawnFor()需要生成角色时自定义出生点选角逻辑
OnActorKilled()(需自行调用)任意 Actor 死亡时计分、重生调度
EndMatch()满足胜利条件时结束比赛

在编辑器里怎么用:在世界场景设置中直接指定,或创建蓝图继承GameModeBase,在类默认值(Class Defaults)里配置 DefaultPawnClass、PlayerControllerClass、GameStateClass 等。

GameMode只存在于服务器。单机游戏中你就是服务器,所以一切正常;但做联机时,客户端拿不到 GameMode——比分这类所有人都要看的数据必须放进 GameState。

2. AGameState

核心职责:存储全局共享的游戏状态,并自动复制(Replication)到所有客户端。剩余时间、双方比分、当前回合数都属于它。

UPROPERTY(Replicated, BlueprintReadOnly) float RemainingTime; UPROPERTY(Replicated, BlueprintReadOnly) int32 TeamAScore;

简单来说 GameMode 决定游戏规则;判断谁赢了,什么时候结束。而GameState是记录游戏状态,给所有人共享数据

3. APlayerController

核心职责:捕获输入、控制视角、管理 UI 交互。它是玩家与游戏世界之间的"代理",每个玩家独立拥有一个。

常用功能:

  • 输入处理:SetupInputComponent()中绑定按键(后续 获取输入篇 详解);
  • 视角控制:持有 CameraManager,管理相机震动、淡入淡出;
  • UI 交互:管理鼠标显示/隐藏、SetInputMode(游戏模式 / UI 模式);
  • 获取玩家状态:GetPlayerState<APlayerState>()拿到自己的战绩数据。

4. APawn 与 ACharacter

APawn:世界中被控制的实体,本身没有智能。它提供AddMovementInput()等移动接口,但"什么时候移动"要听 Controller 的。

ACharacter:最常用的 Pawn 子类,额外拥有:

  • CharacterMovementComponent:处理走/跑/跳/游泳/飞行的移动组件,内置网络同步和碰撞;
  • SkeletalMesh:骨骼网格体,挂上角色模型;
  • 胶囊体碰撞(CapsuleComponent):角色的根碰撞。

简单来说,Pawn像是一个句柄,控制物体如何移动;Charactor是任务角色的类。

Pawn 与 Controller 的接口:Controller 通过Possess()附身 Pawn,通过UnPossess()离开。附身之后,Pawn 收到的输入才有效。

5. AHUD 与 UMG

AHUD:传统的画布绘制类,通过DrawHUD()用代码画准星、血条。现代项目更多把它当作 UMG 的"宿主"。

UMG(Widget):基于控件的 UI 系统,用 UUserWidget 做血条、背包、计分板,是实际开发的主流选择。HUD 小节先了解概念即可,后续会专门展开UMG的详细介绍。

6. APlayerState

核心职责:记录单个玩家的持久数据:昵称、ID、击杀数、死亡数、得分。

和 GameState 的区别:GameState 存"全局局势"(哪队领先),PlayerState 存"个人战绩"(你杀了几个人)。联机时每个客户端都有一份所有玩家的 PlayerState 副本。

7. AAIController

与 PlayerController 平级,但不做输入处理,而是由**行为树(Behavior Tree)和黑板(Blackboard)**驱动。核心函数:

  • RunBehaviorTree():启动行为树;
  • MoveToActor()/MoveToLocation():寻路移动。

这也是"身体与大脑分离"设计的最大受益者:让 AI 接管一个玩家角色,只需AIController->Possess(Character),角色代码一行不用改。

这里暂时不考虑理解这个AIController,简单了解就可以

三、理解一局游戏是如何运行的

了解了每个类的定义,现在把它们放回一个真实场景中:

场景:玩家启动游戏 → 进入一个对战地图 → 控制角色移动 → 击杀敌人获得分数 → 游戏结束时显示胜负。

1. GameMode

玩家启动游戏、地图加载,GameMode第一个登场。它像开赛前检查场地的裁判:这场比赛用哪个地图、每位玩家操控什么角色(DefaultPawnClass)、由什么控制器接管(PlayerControllerClass),都是它说了算。

2. Controller 附身 Pawn

玩家连接进来,GameMode依次生成两样东西:一个PlayerController和一个Character。然后 PlayerController 对 Character 执行Possess(附身)——从这一刻起,按键才有了意义。

同时,GameMode 还生成了一份PlayerState(玩家档案),里面登记着这位玩家的昵称和初始战绩。

3. 按键如何变成移动

玩家按下 W 键,流程是:

  1. PlayerController最先收到输入事件;
  2. 它调用 Character 的移动接口AddMovementInput();
  3. CharacterMovementComponent真正执行移动,并把结果通过网络复制给其他客户端。

注意:Character 自始至终没"决定"过任何事,它只是执行者

4. 数据存储在哪里

玩家击杀一名敌人,数据兵分两路:

  • 个人战绩(击杀数 +1)→ 写入PlayerState。因为战绩属于"这位玩家",且要跟随他直到对局结束;
  • 队伍比分 → 写入GameState。因为比分属于 全局数据 ,且必须同步到所有客户端。

GameMode 此时并不存数据,它只负责裁决:听到击杀事件后,检查胜利条件是否达成。

5. 判断游戏结束

胜利条件达成,*GameMode*判定比赛结束,广播结束事件。结果经由*GameState*同步到每个客户端,最终由*HUD / UMG*把"胜利"画面画到每位玩家的屏幕上。

1. 玩家启动游戏 → GameMode 决定使用哪个地图、哪个 Pawn、哪个 Controller 2. 玩家进入游戏(PostLogin) → GameMode 生成 Pawn、PlayerController 和 PlayerState → Controller 附身(Possess)Pawn 3. 玩家操作(按 W 键) → PlayerController 捕获键盘输入 → 调用 Pawn 的移动函数(AddMovementInput) → CharacterMovementComponent 执行移动,并复制给其他客户端 4. 玩家击杀敌人 → 更新 PlayerState 中的击杀数(个人战绩) → 更新 GameState 中的队伍比分(全局局势) → GameMode 检查胜利条件 5. 游戏结束 → GameMode 判定结束并广播事件 → GameState 同步结果 → HUD / UMG 显示胜负界面
玩家按键 → PlayerController(接收)→ Pawn/Character(执行)→ 数据写入 PlayerState(个人)/ GameState(全局)→ GameMode 裁决 → UI 展示

四、生命周期

梳理整个流程,会发现这些类的生命周期是不一样的

对象创建者生命周期
GameMode引擎(关卡加载时)随关卡,仅服务器
GameStateGameMode随关卡,所有端
PlayerControllerGameMode(玩家加入时)玩家连接期间
PlayerStateGameMode(玩家加入时)整个对局(跨重生)
Pawn / CharacterGameMode(重生时)一次生命,死亡即销毁
HUDPlayerController随本地玩家
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进