概念页
Gameplay 框架
Gameplay Framework
Gameplay 框架 (Gameplay Framework) 是 UE 提供的一组相互配合的类,用来搭建游戏的基本结构:Actor 与组件 (Component) 构成场景中的一切;GameMode 在服务器上定规则并生成玩家;玩家由“控制器 (Controller) + 棋子 (Pawn)”组成;GameState 与 PlayerState 负责把全局与每个玩家的状态复制给所有客户端;GameInstance 跨关卡存活。
类的关系与生命周期
下图按“谁创建谁 / 谁拥有谁”画出框架各类,括号内是生存期。
flowchart TD GI["GameInstance(引擎启动→关闭,跨关卡,不复制)"] --> SS["GameInstance 子系统"] W["World(一张地图)"] --> GM["GameMode(仅服务器,每关卡)"] GM --> GS["GameState(1 个,复制)"] GM --> PS["PlayerState(每玩家 1 个,复制)"] GM --> PC["PlayerController / AIController"] GM --> PW["Pawn / Character"] PC -->|"Possess 附身"| PW PW --> AC["Actor 组件:碰撞、网格、移动……"] PC --> HUD["HUD / 相机(仅人类玩家)"]
Actor 生命周期:加载、生成与销毁
官方把 Actor 实例化分成几条路径,无论哪条,最后都走同一条销毁路径。(Actor Lifecycle)
flowchart TD L["从磁盘加载<br/>PostLoad"] --> I P["PIE 复制<br/>PostDuplicate"] --> I S["SpawnActor<br/>PostSpawnInitialize → PostActorCreated"] --> C["ExecuteConstruction<br/>OnConstruction(蓝图构造脚本)"] D["SpawnActorDeferred<br/>设置属性"] -->|FinishSpawning| C C --> I["PreInitializeComponents → InitializeComponent → PostInitializeComponents"] I --> B[BeginPlay] B --> E["EndPlay(Destroy、关卡切换、流出、PIE 结束、退出)"] E --> G["标记待回收 → GC:BeginDestroy → FinishDestroy"]
图中左侧四条入口分别是关卡加载、PIE 复制、运行时生成和延迟生成;它们汇合到组件初始化和 BeginPlay,结束时都经过 EndPlay 再由 GC 释放。要点(均出自 Actor Lifecycle):
PostLoad只用于从磁盘加载的 Actor,PostActorCreated只用于生成的 Actor,二者互斥;版本修复写在PostLoad。- 延迟生成 (Deferred Spawn):属性勾了 Expose on Spawn 时使用;
SpawnActorDeferred返回一个有效但未完成的实例,先设置参数,再FinishSpawning从构造脚本继续,适合程序化生成。 EndPlay的触发来源:显式Destroy、PIE 结束、关卡切换(无缝旅行或加载地图)、所在流送关卡卸载、生命期到期、程序退出。OnDestroyed是遗留接口,逻辑应移到EndPlay。- 坑:
EndPlay不等于对象已销毁。若s.ForceGCAfterLevelStreamedOut为 false 且子关卡被快速重新加载,Actor 可能被「复活」,局部变量不会重置为默认值。 - 判断对象是否待销毁时,用
FWeakObjectPtr比手动检查更干净;GC 阶段的细节见 垃圾回收与对象生命周期。
各类职责
| 类 | 职责 | 要点 |
|---|---|---|
| Actor | 任何可放进关卡的对象 | 支持变换;可生成、销毁;是组件的容器;负责属性与函数调用的网络复制 |
| Actor 组件 (Actor Component) | Actor 的构件 | 控制移动、渲染、位置、视角等;如场景组件、静态网格组件、相机组件、弹簧臂组件 |
| Pawn | 可被玩家或 AI 控制的 Actor 基类 | 是玩家在世界里的物理表现 |
| Character | 竖直站立、能走跑跳飞游的 Pawn | 自带角色移动组件、骨骼网格组件、胶囊组件 |
| Controller | 无物理表现的 Actor,附身 Pawn 并指挥它 | PlayerController 处理人类输入、显示 HUD;AIController 用行为树、状态树、导航决策 |
| GameMode | 规则与会话结构的核心 | 只存在于服务器;关卡加载、World 创建后第一个实例化的 Actor;可按地图设置;不跨关卡;指定其他框架类并生成玩家 |
| GameState | 所有玩家相关的数据与逻辑 | 团队分数、目标、所有玩家及其 PlayerState 列表;在服务器与客户端间复制 |
| PlayerState | 单个玩家的数据与逻辑 | 生命值、弹药、背包等;每个玩家加入时创建;复制 |
| GameInstance | 整个游戏进程的管理者 | 无物理表现;不复制,服务器和每个客户端各有独立实例;跨关卡持久的数据(如存档系统)放这里 |
| World | 代表一张地图的顶层对象 | 包含持久关卡、GameState、GameMode 及当前 Pawn、Controller 列表 |
| HUD / Camera | 屏幕叠加显示 / 玩家视角 | 每个人类玩家各一份,只对人类玩家有意义 |
| Gameplay Statics | 静态工具类 | 播放声音、生成特效与 Actor、施加伤害、获取玩家 Pawn/Controller 等 |
为什么这样拆分
- 控制与表现分离:Controller 决定“做什么”,Pawn 负责“在世界中怎么呈现与运动”。Pawn 既可以由 PlayerController 附身,也可以由 AIController 附身。
- 权威与复制分离:规则(GameMode)只在权威服务器上运行,客户端拿不到它;所有人都需要看到的状态放在会复制的 GameState / PlayerState 中。
- 生命周期分层:跨关卡的东西放 GameInstance(及其子系统),每关卡的放 GameMode/GameState,每玩家的放 PlayerState。
实际项目中的用法
- 计分、倒计时、比赛阶段:规则判定写在 GameMode,结果写入 GameState 供客户端 UI 读取。
- 玩家的分数、队伍、名字:放 PlayerState;输入处理和 UI 逻辑放 PlayerController;移动、碰撞、动画放 Pawn/Character 及其组件。
- 存档、登录、在线服务(好友、会话、大厅、排行榜):放 GameInstance 或其子系统(如在线子系统 Online Subsystem)。
- Actor 的初始化写在
BeginPlay()而不是构造函数,见 UObject 与反射系统;每帧更新与顺序见 委托与 Tick 机制。 - 这些类大多可以用 C++、蓝图或二者结合(最常见)来定制,见 蓝图与 C++ 协作。
常见坑
- 在客户端代码里获取 GameMode:它只在服务器存在,客户端拿到的是空。客户端需要的信息应放到 GameState/PlayerState。
- 把跨关卡数据放在 GameMode 或 Pawn 上:它们随关卡或角色重生而销毁。
- GameInstance 不复制,不能用它在服务器与客户端之间同步数据。
- Actor 被
Destroy()后,其他对象持有的 UPROPERTY 引用会被置空,使用前须检查,见 垃圾回收与对象生命周期。
GEA 的视角:Actor、组件与玩法基础系统(卷 II 17.1–17.2、17.10)
GEA 第 17 章把本页这类框架称为玩法基础系统,并从架构角度评论了 Unreal:
- 单体层次与冒泡效应:GEA 把 Unreal 的对象类层次作为"单体类层次"的经典例子,并说
Actor类包含渲染、动画、物理、世界交互、音效、网络复制、对象创建销毁、Actor 迭代和消息广播的数据与代码,是功能"冒泡"到根类的典型。 -
分歧(并列记录):本页依据 UE 5.8 文档把 Actor 描述为"组件的容器",移动、渲染、位置、视角等由 Actor 组件负责,Actor 自身负责变换、生成销毁和网络复制。GEA 的描述突出 Actor 承担的子系统职责,UE5 文档的描述突出组件化。GEA 没有说明其描述对应哪个引擎版本;两种说法都保留,细节见 运行时对象模型架构。
- 组件即子系统连接:GEA 说以对象为中心的组件通常代表到某个底层子系统的连接,这正是本页"Actor 组件:碰撞、网格、移动……"的组织方式。
- 高层游戏流程:GEA 认为目标、成功失败和章节推进需要一个高层状态机(Naughty Dog 的任务图还支持并行任务),本页中 GameMode 负责规则、GameState 负责比赛阶段,是 UE 放置这类逻辑的地方(对比归纳),见 游戏世界与游戏对象。
出处
- Gameplay Framework UE 5.8 文档
- Actor Ticking UE 5.8 文档
- Unreal Object Handling UE 5.8 文档
- Objects in Unreal Engine UE 5.8 文档
- Actor Lifecycle UE 5.8 文档
- Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 17 章 17.1–17.2 节
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 17 章 17.10 节
相关页面
游戏开发 · UE5UObject 与反射系统UObject & Reflection System虚幻引擎 (Unreal Engine) 的对象基类是 UObject。在 C++ 类、属性、函数上加 UCLASS/UPROPERTY/UFUNCTION 等宏,再由构建前的预处理工具虚幻头文件工具 (Unreal Header Tool, UHT) 扫描头文件生成代码,引擎就能在运行时“看见”这些类型——这就是反射系统 (Reflection System)。垃圾回收、序列化、编辑器面板、蓝图、网络复制都建立在它之上。游戏开发 · UE5垃圾回收与对象生命周期Garbage Collection & Object LifecycleUE 用标记-清除式的可达性分析管理 UObject 内存:从根集合 (Root Set) 出发沿反射可见的强引用遍历对象图,找不到的对象在下次垃圾回收 (Garbage Collection, GC) 时被删除。因此“谁持有 UPROPERTY 引用”决定了对象活多久;Actor 调用 Destroy() 只是请求销毁,真正释放仍取决于引用是否全部放开。游戏开发 · UE5蓝图与 C++ 协作Blueprint & C++ InteropEpic 官方建议:多数项目混用蓝图 (Blueprint) 与 C++,以 C++ 作为基础、在其上构建蓝图类。C++ 适合“编程”——定义系统;蓝图适合“脚本”——在已有系统上定义具体行为。两者通过反射说明符互相调用:C++ 用 BlueprintCallable/BlueprintReadWrite 等暴露给蓝图,用 BlueprintImplementableEvent/BlueprintNativeEvent 让蓝图实现或覆盖 C++ 声明的函数。游戏开发 · UE5委托与 Tick 机制Delegates & TickUE 有两种驱动游戏逻辑的方式:事件驱动——委托 (Delegate) 在某事发生时回调绑定的函数;轮询驱动——Tick 每帧(或按最小间隔)调用 Actor/组件的更新函数,并按 Tick 组 (Tick Group) 与物理模拟排序。官方建议能用定时器、委托就不用 Tick,必须 Tick 时用 Tick 组和 Tick 依赖保证顺序,避免“差一帧”问题。游戏开发 · UE5Gameplay 能力系统Gameplay Ability SystemGameplay 能力系统 (Gameplay Ability System, GAS) 是 UE 用来构建「Actor 可拥有并反复触发的能力」的框架:能力系统组件 (Ability System Component, ASC) 是持有者,Gameplay 能力 (Gameplay Ability) 编排执行过程,属性集 (Attribute Set) 存数值,Gameplay 效果 (Gameplay Effect, GE) 改数值和标签,Gameplay 标签 (Gameplay Tags) 做状态与互斥,Gameplay Cue 负责表现。它内建复制与客户端预测,代价是概念多、上手重,游戏开发 · UE5MassEntity 数据导向框架MassEntity FrameworkMassEntity 是 UE5 面向玩法的数据导向 (Data-Oriented) 计算框架,属于实体-组件-系统 (Entity Component System, ECS) 一类设计:实体 (Entity) 只是一个 ID 加上一组片段 (Fragment) 数据,相同组成的实体归入同一原型 (Archetype) 并按内存块 (Chunk) 连续存放,无状态的处理器 (Processor) 通过实体查询 (EntityQuery) 批量处理片段。它适合成千上万个同质对象(人群、交通),MassGameplay 插件在其上提供表现、生成、LOD、复制、StateTree 等功能。游戏开发 · UE5增强输入Enhanced Input增强输入 (Enhanced Input) 是 UE5 默认启用的输入插件,把输入拆成四层:输入动作 (Input Action) 表示“玩家想做什么”,输入映射上下文 (Input Mapping Context) 规定“哪些按键在什么情境下触发它”,输入修饰器 (Input Modifier) 预处理原始值,输入触发器 (Input Trigger) 判定是否触发。上下文可在运行时按优先级增删,从而用数据资产而非代码处理情境切换、按键冲突与改键。游戏开发 · UE5网络复制与 RPCNetwork Replication & RPCUE 采用服务器权威 (Server-Authoritative) 的客户端-服务器模型:游戏真正在服务器上进行,服务器把状态复制 (Replication) 给客户端,客户端通过远程过程调用 (Remote Procedure Call, RPC) 向服务器请求操作。开发者需要显式声明哪些 Actor、属性、函数要走网络,并借助所有权、网络角色、相关性、优先级控制“发给谁、发多少”。UE 5.8 提供通用复制系统、Replication Graph 和实验性的 Iris 三套复制系统。游戏开发 · UE5AI 感知、EQS 与导航AI Perception, EQS & NavigationAI 的感官层由三块组成:AI 感知 (AI Perception) 组件挂在 AIController 上监听视觉/听觉/伤害等刺激并更新黑板;环境查询系统 (EQS) 用生成器产生候选项、先过滤后打分,回答「哪里最好」;导航系统从碰撞几何生成分瓦片的导航网格 (NavMesh),按多边形代价寻路,并提供 RVO 与 Detour Crowd 避让。它们为行为树/StateTree 提供输入。游戏开发 · UE5Chaos 物理与碰撞Chaos Physics & CollisionChaos 是 UE5 的物理与破碎系统。日常最常打交道的是碰撞模型:每个物理体有对象类型 (Object Type) 和对其他类型的 Block/Overlap/Ignore 响应,结果由双方共同决定;Hit 与 Overlap 事件都要显式开启。骨骼网格通过物理资产 (Physics Asset) 获得刚体与约束(布娃娃、物理动画);Chaos 破碎基于几何集合 (Geometry Collection) 的分级断裂、簇阈值、连接图与缓存回放,并能把事件交给 Niagara。物理体用盒/球/胶囊/凸包代理,原理对应游戏数学中的包围体与相交测试。游戏开发 · UE5子系统Subsystems子系统 (Subsystem) 是自动实例化、生命周期绑定在宿主对象上的类:Engine、Editor、GameInstance、World、LocalPlayer 五种。宿主创建时自动创建并 Initialize(),宿主关闭时 Deinitialize(),之后无引用即被 GC。它替代了「继承 GameInstance 塞管理器」的老做法,自带按类型的蓝图节点和 Python 访问,特别适合插件。官方编程页只列四种,World 子系统依据 5.8 Python API 补充。游戏开发 · UE5行为树与 StateTreeBehavior Tree & StateTreeUE 的 AI 决策有两套工具:行为树 (Behavior Tree) + 黑板 (Blackboard) 是事件驱动的,条件写成装饰器 (Decorator),用 Simple Parallel、Services 和 Observer Aborts 代替传统并行节点;StateTree 是结合了行为树选择器和状态机转换的通用分层状态机,只在转换触发时按需选择状态,激活路径上的任务并发运行,通过属性绑定传递数据,也是 Mass 的行为层。优先级抢占多的战斗 AI 适合行为树,状态显式、分层或大规模的场景适合 StateTree。游戏开发 · UE5存档系统SaveGameUE 的存档围绕自定义的 USaveGame 子类进行:保存时把需要持久化的数据从游戏世界拷进 SaveGame 对象,再用 UGameplayStatics 写入某个存档槽(槽名 + 用户索引);读档时反过来。官方推荐用 AsyncSaveGameToSlot 异步保存,避免掉帧,也避免某些平台的认证问题。游戏开发 · UE5Game Features 与模块化玩法Game Features & Modular GameplayGame Features 与 Modular Gameplay 两个插件让开发者把一个玩法功能做成独立的插件,可以单独启用或停用。功能本身由一个 GameFeatureData 资产里的 Action 列表描述,最常用的是 Add Components:把插件里的组件按需挂到已有的 Actor 类上。这样主工程的代码保持干净,无关功能之间不会意外产生依赖,对需要长期增减功能的线上产品尤其重要。游戏开发 · UE5角色移动组件与 MoverCharacter Movement Component & Mover角色移动组件 (CMC) 用「客户端预测 + 服务器校验 + 纠正后重放」实现联网移动:自主代理先在本地移动并把操作存起来,用 ServerMove RPC 发给服务器重演,位置不符时服务器用 ClientAdjustPosition 纠正,客户端再按保存的操作重放;模拟代理只应用复制下来的移动并做平滑。实验性插件 Mover 计划接替 CMC,改用共享时间线、回滚与重模拟的模型,并且更模块化。游戏开发 · UE5相机系统Camera System传统相机链路是:PlayerController 持有 PlayerCameraManager,后者维护一个视图目标 (view target),通过 CalcCamera 取得相机组件或 Actor 的位置朝向,并在不同目标之间混合。实验性的 Gameplay Camera System 把相机行为做成数据资产:一个 Camera Asset 包含多个由节点网络构成的 Camera Rig、进出转换,以及决定当前使用哪个 Rig 的 Camera Director。游戏开发 · UE5音频系统与 MetaSoundsAudio System & MetaSoundsUE5 的音频资产分三层:音源 (Sound Source) 负责产生声音,UE5 主推 MetaSounds,它是一张由设计师搭建的数字信号处理 (DSP) 图,能精确到单个采样;分组与混音用 Sound Class 和 Sound Class Mix 批量调整音量和音高;空间与资源由 Sound Attenuation(随距离衰减和空间化)和 Sound Concurrency(限制同时播放数量)控制。需要和节拍对齐的玩法可以用 Quartz 做精确到采样的调度。游戏开发组件模式Component Pattern组件模式 (Component Pattern) 让一个实体横跨多个领域(输入、物理、图形、AI……),同时不让这些领域彼此耦合:每个领域的代码放进自己的组件类,实体本身退化为组件的容器。它是现代引擎实体模型的基础,代价是对象变成需要正确装配的一组对象,组件之间如何通信也成了要做的设计决策。游戏开发运行时引擎分层架构Runtime Engine ArchitectureGregory 把游戏视为“软实时、交互式、基于代理的计算机模拟”,把游戏引擎定义为数据驱动、可复用来做多款游戏的软件。运行时引擎按层组织:从目标硬件、驱动、操作系统、第三方 SDK、平台无关层、核心系统、资源管理器,到渲染、物理、动画、音频、网络等子系统,再到游戏性基础层和游戏专属子系统;上层依赖下层,避免循环依赖。游戏开发游戏世界与游戏对象Game World & Game Objects游戏由玩法 (gameplay) 而不是技术定义;游戏机制 (game mechanics) 是支配游戏中各实体交互的规则,以及目标、成败标准、玩家能力、非玩家实体和整体流程(GEA 引用的论文称实现玩法的软件系统为游戏的 G 因子)。大多数游戏世界由静态元素和动态元素组成,划分为若干世界块,并由高层游戏流程组织玩家目标;动态元素通常实现为游戏对象 (GO),引擎提供的建模设施称为游戏对象模型,且分为工具侧和运行时两套(GEA4 卷 II 16、16.1–16.2)。游戏开发运行时对象模型架构Runtime Object Model Architectures玩法基础系统 (gameplay foundation system) 是位于"引擎与游戏分界线"附近、供构建游戏规则和动态元素的一组运行时组件,其中最复杂的是运行时对象模型:它在运行时实现世界编辑器展示给策划的抽象对象模型。GEA 把架构分为两大类:以对象为中心(每个工具侧对象对应一个或一小组类实例)和以属性为中心(对象只是一个 id,属性分散在按属性类型划分、以 id 为键的表里)。前者从单体类层次走向组合与组件,后者更省内存、更缓存友好、更易数据驱动,但难以表达属性间关系、也更难调试(GEA4 卷 II 17.1–17.2)。综合引擎运行时架构总览Engine Runtime Architecture Overview本页把 wiki 中分散在 GEA 第 1、6、8、17 章及 GPP、UE5 相关页面里的内容串成一条线,回答"一个游戏引擎在运行时是怎样组织起来的":静态结构上是自下而上的分层,上层依赖下层;启动关闭按依赖顺序显式进行;每一帧由主循环驱动各子系统批量更新,游戏对象的逻辑被安排在子系统阶段之间,并按依赖分桶或设先后关系;多核上一帧被拆成成百上千个作业;玩法基础系统(对象模型、事件、脚本、世界加载流送、高层流程)位于引擎与游戏的分界线附近。各结论的细节与出处见所链接的概念页。游戏开发游戏循环与更新方法Game Loop & Update Method游戏循环 (Game Loop) 让游戏时间的推进与玩家输入和处理器速度脱钩:每一轮非阻塞地处理输入、更新状态、渲染,并跟踪真实时间来控制节奏;最常推荐的做法是“固定更新步长、可变渲染”。更新方法 (Update Method) 是它的搭档:世界维护一组对象,每个对象实现一个模拟“一帧”行为的 update(),每帧依次调用。两者和组件模式一起常被视为游戏引擎的核心。综合游戏编程模式选型:解耦与性能Choosing Game Programming Patterns本页把《Game Programming Patterns》里的 19 个模式放到同一张取舍图上:大多数模式要么为了解耦(降低改代码时需要装进脑子里的知识量),要么为了性能(利用对数据和硬件的具体假设),而这两个目标经常互相拉扯。下面先讲全书的定位和 Nystrom 的架构观,再给出按问题选模式的路线和与 UE 的对照。