UE面试题|Gameplay框架、UE数据结构
使用了快一年半的UE也没有完全了解GamePlay框架到底是什么。这时突然有一个面试的机会,正好上一次面试没有把Gameplay框架回答完整,所有这一次想着用10个题目来建立对这个的初步了解。
GamePlay框架
使用了快一年半的UE也没有完全了解GamePlay框架到底是什么。这时突然有一个面试的机会,正好上一次面试没有把Gameplay框架回答完整,所有这一次想着用10个题目来建立对这个的初步了解。
-
简述 UE Gameplay 框架的核心类及其职责
- 核心类包括这样几种,首先是UObject、AActor、APawn、ACharacter、AController、AGamemode、AGameState、APlayerState.UGameInstance
- 反射是用宏为提供引擎和编辑器各种功能,封装你的类。UObject是所有对象的基类,他是继承里面最头上的那个,可以有像序列化,反射,GC(垃圾回收)。而Actor是指可以防止在关卡中的一个实体,可以有位置,组件以及网络同步的能力。而APawn是可以控制游戏实体,比如角色和AI,而UGameInstance是快关卡存在的一个全局管理器。
-
GameMode、GameState 和 PlayerState 在多人游戏中的复制行为有何不同?
- 用一个简单的网络游戏来解释,GameMode是存在于服务器,不复制到客户端,而GameState是在服务器创建然后复制到客户端,用来同步全局的状态比较倒计时和比分。而PlayerState是每一个玩家和GameState相同,也是服务器复制到客户端
-
. 为什么 Controller 和 Pawn 要分离?这样设计的好处是什么?
考察点:架构设计思想
- Controller 生命周期长于 Pawn(如角色死亡后 Controller 仍存在)。
- 支持切换控制对象(如观战模式、复活机制)。
- 逻辑解耦:输入、相机、UI 等由 Controller 处理,物理表现由 Pawn 处理。
- 网络同步更清晰:Controller 只存在于本地或服务器,Pawn 可复制。
4. UGameInstance 的作用是什么?什么数据应该放在 GameInstance 中?
考察点:生命周期与数据管理
作用:在整个游戏进程(从启动到退出)中唯一存在,不受关卡切换影响。
适用场景
:
- 跨关卡数据(如玩家总金币、设置选项)
- 存档系统管理
- 在线子系统(会话、好友、排行榜)
- 全局事件总线或服务管理器
5. Pawn 和 Character 有什么区别?何时使用 Character?
考察点:类继承与功能选择
Pawn:基础可控制实体,无默认移动或碰撞。
Character
:继承自 Pawn,内置:
- CapsuleComponent(碰撞)
- SkeletalMeshComponent(骨骼网格)
- CharacterMovementComponent(行走、跳跃、重力等)
使用 Character:当需要人形角色(带移动、动画、碰撞)时。
6. 描述一个玩家从进入游戏到控制角色的完整流程(含关键类的创建顺序)。
考察点:生命周期与初始化流程
典型流程:
- 启动游戏 → 创建
UGameInstance- 加载关卡 → 创建
UWorld和Level- 实例化
AGameMode(仅服务器)GameMode创建AGameState- 玩家连接 → 创建
PlayerController和PlayerStateGameMode调用SpawnDefaultPawnFor()生成Pawn(如 Character)PlayerController::Possess(Pawn)→ 玩家开始控制角色
7. 如何实现跨关卡的数据持久化?为什么不能把数据存在 GameMode 或 Pawn 中?
考察点:生命周期理解
GameMode/Pawn:随关卡卸载而销毁,无法跨关卡保留。
正确做法
:
- 使用
UGameInstance或其子系统(如SaveGameSubsystem)- 使用
USaveGame配合磁盘存档- 利用
PlayerState(若需网络同步且关卡间保留)
8. Gameplay 框架中哪些类是 UObject,哪些是 Actor?为什么这样区分?
考察点:引擎底层设计
UObject 派生
(无位置、不可放置):
UGameInstance,UPlayer,UWorld(特殊 UObject)Actor 派生
(有位置、可放置、可网络复制):
APawn,AController,AGameMode,AGameState,APlayerState原因:Actor 需要支持变换、Tick、组件、网络复制等游戏世界特性;UObject 更轻量,适合管理器类。
9. PlayerController 和 PlayerState 的关系是什么?各自负责什么?
考察点:职责划分
PlayerController
:
- 本地存在(客户端有自己的 PC,服务器也有)
- 处理输入、HUD、相机、本地决策
- 不复制(每个端独立)
PlayerState
:
- 服务器创建,复制到所有客户端
- 存储需要同步的玩家数据(ID、分数、队伍、状态)
一对一绑定:每个 PlayerController 对应一个 PlayerState
10. 如何在 Gameplay 框架中合理分配 C++ 与蓝图的职责?
考察点:工程实践与性能意识
C++ 实现
:
- 核心框架类(GameMode、Character 基类、Subsystem)
- 性能敏感逻辑(移动、伤害计算、状态机)
- 网络同步逻辑(Replicated 属性、RPC)
蓝图实现
:
- 关卡特定逻辑(LevelScriptActor)
- UI 交互、动画蒙太奇触发
- 美术/策划可配置的行为(通过暴露变量或函数)
原则:底层通用逻辑用 C++,上层灵活逻辑用蓝图,通过
BlueprintImplementableEvent或BlueprintNativeEvent桥接。
UE数据结构
1. UE 中常用的动态数组是什么?它与 C++ 标准库中的 std::vector 有何异同?
- ue是使用TArray作为动态数组。作为动态数组它是支持随机访问和自动扩容的。同时还指针UE的反射系统,支持序列化以及垃圾回收。
- 默认使用 UE 的内存分配器(如
FMemory),可定制 Allocator。 - 提供更多游戏开发友好接口(如
AddUnique,FindByPredicate等)
2. UE 中如何实现哈希表?TMap 和 TSet 的底层原理是什么?
TMap<Key, Value>和TSet<Element>基于开放寻址法(Open Addressing)实现,而非链表或红黑树。- 使用线性探测(Linear Probing)解决冲突。
- 支持自定义 Key 的 Hash 函数和 Equality 函数。
- 与
std::unordered_map类似,但集成 UE 内存管理和序列化系统。
3. UE 中的结构体(UStruct)和类(UClass)在内存布局上有何不同?
- 答案要点:
UStruct(如USTRUCT()标记的结构体)是值类型,通常栈分配或内嵌在其他对象中,不参与 GC。UClass衍生自UObject,是引用类型,堆分配,受 UE 垃圾回收系统管理。UStruct可包含UPROPERTY(),支持反射和蓝图访问,但无生命周期管理。
3. UE 中的 TSharedPtr 和 TWeakPtr 是如何工作的?它们与 C++ 的 std::shared_ptr 有何区别?
- 答案要点:
TSharedPtr是引用计数智能指针,TWeakPtr是弱引用,避免循环引用。- UE 版本支持线程安全选项(通过模板参数指定)。
- 可与 UObject 系统配合使用(但通常 UObject 使用
UPROPERTY()+ 引用而非智能指针)。 - 与
std::shared_ptr功能类似,但使用 UE 内存分配器,且可在非 C++11 环境下工作(历史原因)。
4. UE 中的结构体(UStruct)和类(UClass)在内存布局上有何不同?
- 答案要点:
UStruct(如USTRUCT()标记的结构体)是值类型,通常栈分配或内嵌在其他对象中,不参与 GC。UClass衍生自UObject,是引用类型,堆分配,受 UE 垃圾回收系统管理。UStruct可包含UPROPERTY(),支持反射和蓝图访问,但无生命周期管理。
5. UE 如何处理大型数据集合的内存对齐和缓存友好性?举例说明。
- 答案要点:
- 使用
TArray连续内存提高缓存命中率。 - 支持自定义 Allocator(如
TInlineAllocator<N>将小数组放在栈上)。 - 对频繁访问的数据(如组件数组)推荐使用 结构体数组(AoS) vs 数组结构体(SoA) 设计,ECS 架构(如 Mass Entity)采用 SoA 提升性能。
- 使用
6. 解释 UE 中的“稀疏数组”(TSparseArray)和“压缩稀疏数组”(TCompressedSparseArray)的用途。
- 答案要点:
TSparseArray:允许高效插入/删除,保留元素索引(即使中间有空洞),常用于UObject的属性复制或网络同步。TCompressedSparseArray:进一步压缩存储,仅存储有效元素及其索引映射,节省内存。- 两者都支持 O(1) 访问(通过间接索引),适合频繁增删但需保持 ID 稳定的场景。
7. UE 中的 FScriptArray、FScriptMap、FScriptSet 是什么?为什么需要它们?
- 答案要点:
- 这些是 UE 反射系统内部使用的“脚本化容器”,用于在运行时动态操作
TArray/TMap/TSet。 - 蓝图或网络复制系统通过它们访问容器内容,而无需知道具体模板类型。
- 它们是未模板化的底层结构,配合
UProperty实现泛型操作。
- 这些是 UE 反射系统内部使用的“脚本化容器”,用于在运行时动态操作
8. 如何在 UE 中实现一个支持蓝图暴露的自定义数据结构?
- 答案要点:
- 使用
USTRUCT(BlueprintType)标记结构体。 - 成员变量用
UPROPERTY()声明。 - 若需复杂逻辑,可封装为
UFUNCTION(BlueprintCallable)的静态工具函数。 - 注意:蓝图不支持模板,因此不能直接暴露
TArray<MyStruct>以外的泛型容器。
- 使用
9. UE 的垃圾回收(GC)如何影响数据结构的设计?举例说明应避免的情况。
- 答案要点:
- 只有继承自
UObject的对象受 GC 管理。 - 在
TArray<UObject*>中,若未用UPROPERTY()声明,GC 无法追踪,可能导致悬空指针。 - 应避免在非
UObject类中裸存UObject*,除非用TWeakObjectPtr或标记为UPROPERTY()。 - 循环引用(如 A 引用 B,B 引用 A)会导致内存泄漏,需用
TWeakObjectPtr打破。
- 只有继承自
10. UE5 中引入的 Chaos 物理系统或 Niagara 粒子系统使用了哪些特殊的数据结构优化?
- 答案要点(选答方向):
- Chaos:使用并行友好的空间分区结构(如 BVH、Grid-based Broadphase),支持 SIMD 加速。
- Niagara:采用 SoA(Structure of Arrays)存储粒子属性,提升 GPU/CPU 缓存效率;使用计算着色器处理大规模数据。
- 两者都强调数据局部性和多线程安全性,避免传统面向对象设计带来的性能瓶颈。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)