1. 项目概述:为什么AIController与RPC是UE4面试的“硬通货”?
如果你正在准备一场UE4客户端或网络同步方向的面试,尤其是瞄准中高级岗位,那么“AIController的网络同步”和“RPC的正确使用”这两个话题,几乎可以肯定是面试官手中的“王炸”问题。它们不像“什么是蓝图接口”那样基础,也不像“渲染管线优化”那样过于深入特定领域。它们恰好卡在了一个核心的十字路口:既要深刻理解UE4的Gameplay框架(Controller、Pawn、Actor的关系),又要精通网络同步模型(客户端-服务器架构、所有权、RPC),同时还得具备解决实际线上问题的能力(比如“为什么我的AI在客户端不动了?”)。我见过太多简历上写着“精通UE4网络同步”的候选人,在这两个问题上折戟沉沙。今天,我就结合自己踩过的坑和项目里的实战经验,把这套“组合拳”拆开揉碎了讲给你听,让你不仅能回答面试问题,更能理解背后的设计哲学和避坑指南。
简单来说,这个主题探讨的核心是:
如何在多玩家网络游戏中,让由AI控制的角色(AIController)的行为,在不同客户端上正确、高效且可控地同步。
这绝不仅仅是调用一个
Server
或
Client
RPC那么简单。它涉及到AIController的生成与归属权、移动指令的发起与验证、RPC的可靠性与执行目标选择等一系列环环相扣的决策。理解透了它,你对UE4网络层的认知会上一个大台阶。
2. 核心概念深度拆解:AIController与RPC的“前世今生”
在动手写代码之前,我们必须把地基打牢。很多同步问题,根源在于对基本概念的理解有偏差。
2.1 AIController:它到底是谁?在哪里?
AIController是Controller的子类,而Controller是UE4中用于“控制”Pawn的逻辑实体。你可以把它理解为一个“驾驶员”。PlayerController是真人玩家的“驾驶员”,而AIController则是AI逻辑的“驾驶员”。
关键点一:AIController的生成与存在性。 默认情况下,在Listen Server(监听服务器)或Dedicated Server(专用服务器)模式下,AIController 只在服务器端生成和存在 。这是UE4的默认设计,因为AI的决策逻辑(如寻路、选择目标)被认为是权威的、应该由服务器来执行的。客户端通常只接收服务器同步过来的Pawn状态(位置、旋转),并进行视觉表现。
关键点二:AIController的“拥有权”。 在UE4网络模型中,一个Actor(包括Controller)必须有一个“Owner”(不是指C++里的UObject Owner,而是网络意义上的“拥有者”)。PlayerController通常由连接过来的客户端“拥有”。而AIController,默认情况下由 服务器拥有 。这意味着,对这个AIController调用RPC时,你必须要清楚RPC的执行目标是谁。
面试高频问题:“客户端需要AIController吗?” 答案是: 视情况而定,但通常不需要,也不推荐客户端拥有完整的AIController。
- 不需要 :如果AI的行为完全由服务器驱动(服务器计算移动,客户端只做表现),那么客户端根本不需要AIController实例。客户端上的AI Pawn只是一个“提线木偶”。
-
不推荐
:如果你为了让客户端也能调用
MoveToLocation而手动在客户端生成一个AIController,你会立刻面临严重的同步和作弊问题。两个AIController(服务器一个,客户端一个)会发出两套可能矛盾的移动指令,游戏状态将彻底混乱。
那么,社区里讨论的“Client-side AI Controller”是什么场景?通常是一些特殊的、对实时性要求极高且逻辑简单的客户端本地特效AI,比如一群纯粹为了烘托气氛、不与游戏核心逻辑交互的飞鸟。即便如此,也需要极其小心地设计,避免与服务器权威状态冲突。
2.2 RPC(远程过程调用):网络游戏的“指挥棒”
RPC是UE4网络同步的基石,它允许你在一个机器(如服务器)上调用一个函数,而在另一个机器(如客户端)上执行它。
三种核心RPC:
- Server RPC (UFUNCTION(Server, Reliable/Unreliable)) : 只能在客户端调用,在服务器上执行。用于客户端向服务器发送请求,如“我要攻击”、“我要移动到这里”。
- Client RPC (UFUNCTION(Client, Reliable/Unreliable)) : 只能在服务器调用,在指定的客户端上执行。用于服务器向特定客户端发送通知,如“你被击中了”、“播放这个特效”。
- NetMulticast RPC (UFUNCTION(NetMulticast, Reliable/Unreliable)) : 只能在服务器调用,在服务器和 所有客户端 上执行。用于广播全局事件,如“爆炸了”、“游戏开始”。
面试必考细节:RPC的执行者与目标。
这是最容易混淆的地方。以
UFUNCTION(Client)
为例:
// 在服务器端的某个Actor(比如AIController)里
void AAIController::TellClientSomething()
{
// 这个RPC会在“这个Actor的拥有者客户端”上执行。
// 如果这个AIController由服务器拥有,它没有对应的客户端拥有者,那么这个RPC将无处可去,不会执行!
ClientRPCFunction();
}
对于AIController,由于它通常由服务器拥有,你 无法 直接从这个AIController上调用一个Client RPC到某个玩家的客户端。你需要找到正确的“信使”。通常,这个信使是:
- 玩家控制的Pawn :它被某个客户端拥有。
- 玩家的PlayerController :它直接被某个客户端拥有。
- GameState :它在所有机器上存在,且服务器拥有,适合广播(NetMulticast)。
Reliable vs Unreliable:
- Reliable(可靠) :保证送达,且按顺序送达。用于关键指令,如技能释放、物品拾取。但滥用会导致网络缓冲区堆积(Buffer)。
- Unreliable(不可靠) :不保证送达,可能丢失,也可能乱序。用于高频、可容忍丢失的数据,如每帧的位置更新(实际上位置更新通常用属性同步Property Replication,而非RPC)。
3. 实战架构设计:四种经典场景与选型思路
理解了概念,我们来看实战。面对“AI移动同步”这个问题,根据你的游戏类型和AI角色重要性,至少有四种主流架构。选择哪一种,直接决定了你代码的复杂度和后期的维护成本。
3.1 场景一:完全服务器权威AI(最常用、最推荐)
这是MMO、MOBA、战术竞技等严肃网络游戏的标准做法。
- 设计 :AIController仅存在于服务器。AI的感知(看见玩家)、决策(选择目标)、移动(寻路到某点)全部在服务器进行。
-
同步方式
:
-
服务器AIController调用
MoveToLocation()。 -
AI Pawn的移动组件(如
CharacterMovementComponent)在服务器上计算移动。 -
由于AI Pawn的
bReplicates设为true,且其位置(ReplicatedMovement)被设置为同步,服务器会自动将移动结果(位置、速度)同步给所有客户端。 - 客户端收到位置更新后,驱动本地AI Pawn的骨骼网格体移动,实现视觉同步。
-
服务器AIController调用
- 优点 :绝对防作弊,逻辑统一,状态一致。符合UE4默认设计,开发阻力小。
- 缺点 :所有AI计算负载都在服务器,服务器压力大。客户端看到的移动有网络延迟。
- RPC使用 :在这种模式下, AI移动本身通常不直接使用RPC 。移动是状态同步(属性复制)。RPC可能用于AI触发的特定事件,比如AI释放了一个技能(Server RPC通知服务器计算伤害,NetMulticast RPC播放全服特效)。
3.2 场景二:客户端预测式移动(用于玩家角色,AI慎用)
这是FPS游戏中玩家角色移动的常见模式,用于AI需要非常谨慎。
- 设计 :客户端拥有一个AIController(或移动逻辑),可以立即响应并移动本地AI角色,同时将移动意图(输入)通过Server RPC发送给服务器。服务器验证后执行权威移动,并将结果同步回来,客户端进行纠偏(Reconciliation)。
- 对于AI :这极其复杂。你需要在客户端模拟AI的决策逻辑,并保证与服务器的逻辑完全一致(几乎不可能)。一旦出现分歧(客户端AI认为该追击,服务器AI认为该撤退),纠偏会变得非常诡异。 除非AI逻辑极其简单且确定(如巡逻固定点),否则不推荐。
-
RPC使用
:客户端AI逻辑调用
Server_MoveToRPC,将目标点发给服务器。服务器验证后执行移动。
3.3 场景三:客户端自主视觉表现(“假AI”)
这就是开头论坛帖子可能想尝试的。AI没有游戏逻辑意义,纯装饰。
- 设计 :在客户端本地生成AI Pawn和AIController,其移动、行为完全在客户端计算和表现,不与服务器同步任何状态。服务器甚至不知道它的存在。
- 用途 :场景中的小动物、飘动的旗帜、无关紧要的NPC背景板。
- RPC使用 :完全不需要RPC,因为不涉及网络。
-
重要配置
:需要在项目设置中开启“Allow Client Side Navigation”,客户端的导航系统才会工作。但即使开启了,如论坛帖子所述,直接调用
MoveToLocation可能仍不工作,因为客户端的导航网格(NavMesh)可能没有正确生成或加载。你需要确保客户端也有完整的导航数据。
3.4 场景四:混合模式 - 服务器决策,客户端执行(高阶)
一种折中方案,平衡服务器压力和响应速度。
- 设计 :服务器负责AI的“决策”(目标是谁,是否攻击),这个决策结果通过RPC(如Client RPC)下达给客户端。客户端收到指令后, 使用本地的AIController执行具体的移动和动画 。
- 关键 :服务器必须保持 最终权威 。例如,服务器定期检查客户端AI的位置,如果偏离预期(可能是作弊或Bug),服务器可以强制同步一个正确位置(通过设置Pawn的Location,这会覆盖客户端移动),或者发送一个修正指令。
-
RPC使用
:服务器通过某个中介(如GameMode)调用一个在AI Pawn上的Client RPC,通知它“向X点移动”。AI Pawn在客户端收到后,调用本地AIController的
MoveToLocation。 - 优点 :移动响应快(无网络延迟),服务器只做决策,计算压力小。
- 缺点 :架构复杂,需要设计一套完善的指令与状态校验机制,防作弊能力弱于纯服务器权威。
4. 实战代码解析:从零构建一个同步AI敌人
我们以最经典、最安全的
场景一(完全服务器权威)
为例,手把手实现一个会被同步的AI敌人。假设我们有一个
ABP_Enemy
类继承自
Character
。
4.1 第一步:设置Actor与组件复制
首先,确保你的AI Pawn能正确地在网络上存在和同步。
在
ABP_Enemy
的头文件(.h)中:
UCLASS()
class AABP_Enemy : public ACharacter
{
GENERATED_BODY()
public:
AABP_Enemy();
protected:
virtual void BeginPlay() override;
// 声明一个服务器权威的移动目标RPC
UFUNCTION(Server, Reliable, WithValidation)
void Server_MoveToLocation(const FVector& Location);
bool Server_MoveToLocation_Validate(const FVector& Location);
void Server_MoveToLocation_Implementation(const FVector& Location);
// 用于测试的按键绑定(仅服务器或拥有客户端输入有效)
void TestMoveCommand();
};
在
ABP_Enemy
的源文件(.cpp)中,构造函数里进行关键设置:
AABP_Enemy::AABP_Enemy()
{
// 1. 将此Actor设置为在网络中复制。这是最重要的开关。
bReplicates = true;
// 2. 设置移动组件的复制。这确保了移动更新(位置、旋转、速度)会从服务器复制到客户端。
GetCharacterMovement()->SetIsReplicated(true);
// 3. (可选但推荐)设置一个较低的NetUpdateFrequency,因为AI不需要像玩家那样高频更新。
NetUpdateFrequency = 5.0f; // 每秒更新5次
MinNetUpdateFrequency = 2.0f;
}
注意 :
bReplicates=true是让这个Actor存在于所有客户端的前提。GetCharacterMovement()->SetIsReplicated(true)是让移动同步生效的关键。很多新手只设了前者,结果发现AI在客户端是“太空步”(动画在播,位置不动),就是因为移动没同步。
4.2 第二步:创建并配置AIController
创建一个
AAIC_Enemy
类继承自
AAIController
。
在
AAIC_Enemy
的构造函数中:
AAIC_Enemy::AAIC_Enemy()
{
// AIController默认bReplicates = false,且通常我们不需要它复制。
// 因为它只存在于服务器,客户端不需要它的状态。
bReplicates = false; // 保持false即可
// 设置感知组件等AI模块...
}
关键理解
:这里
bReplicates=false
是故意的。我们
不
希望AIController本身被复制到客户端。客户端不需要它的逻辑实例,只需要看到它控制的结果(Pawn的移动)。
4.3 第三步:在服务器上生成并控制AI
游戏开始时(例如在GameMode中),在服务器上生成AI并为其分配AIController。
// 在GameMode或某个管理类中
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 确保只在服务器端生成AI
if (HasAuthority())
{
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
// 在随机位置生成一个敌人
FVector SpawnLocation = ...; // 你的生成逻辑
AABP_Enemy* NewEnemy = GetWorld()->SpawnActor<AABP_Enemy>(EnemyClass, SpawnLocation, FRotator::ZeroRotator, SpawnParams);
if (NewEnemy)
{
// 为这个敌人创建一个AIController
AAIC_Enemy* EnemyAIController = GetWorld()->SpawnActor<AAIC_Enemy>(AIControllerClass);
if (EnemyAIController)
{
// 关键!让AIController接管(Possess)这个敌人Pawn。
// 这行代码只在服务器执行,客户端不会执行,因为AIController只在服务器存在。
EnemyAIController->Possess(NewEnemy);
}
}
}
}
4.4 第四步:实现移动指令与RPC
现在,我们需要一个机制来让AI移动。假设我们通过一个按键来测试。
在
ABP_Enemy::BeginPlay
中绑定输入(仅用于测试):
void AABP_Enemy::BeginPlay()
{
Super::BeginPlay();
// 只有被玩家控制的Pawn(或服务器)才能响应按键输入。
// 这里我们简单判断是否有Authority(服务器),或者是否被本地玩家控制。
// 实际项目中,移动指令可能来自AI的行为树,而不是按键。
if (IsLocallyControlled() || HasAuthority())
{
// 绑定一个测试按键,比如'M'
if (APlayerController* PC = GetWorld()->GetFirstPlayerController())
{
PC->InputComponent->BindAction("TestMove", IE_Pressed, this, &AABP_Enemy::TestMoveCommand);
}
}
}
void AABP_Enemy::TestMoveCommand()
{
// 生成一个随机目标点
FVector RandomDestination = GetActorLocation() + FVector(FMath::RandRange(-500, 500), FMath::RandRange(-500, 500), 0);
// 调用Server RPC,将移动请求发送到服务器
Server_MoveToLocation(RandomDestination);
}
实现Server RPC:
// _Validate函数用于简单的防作弊验证(可选但推荐)
bool AABP_Enemy::Server_MoveToLocation_Validate(const FVector& Location)
{
// 例如:检查目标点是否在合理范围内(防止客户端传一个超远坐标)
return (GetActorLocation() - Location).SizeSquared() < 1000000.0f; // 例如1000米内
}
void AABP_Enemy::Server_MoveToLocation_Implementation(const FVector& Location)
{
// 这个函数只在服务器上执行!
// 获取控制这个Pawn的AIController
if (AAIController* AIController = Cast<AAIController>(GetController()))
{
// 服务器权威地执行移动指令
AIController->MoveToLocation(Location);
// 如果需要,可以在这里广播一个NetMulticast RPC,让所有客户端播放一个“开始移动”的特效或声音。
// Multicast_PlayMoveEffect();
}
}
流程梳理 :
-
玩家在客户端按M键,触发
TestMoveCommand。 -
TestMoveCommand调用Server_MoveToLocation(RandomDestination)。这是一个Server RPC。 -
UE4网络层将这个函数调用和参数
RandomDestination打包,发送给服务器。 -
服务器收到后,执行
Server_MoveToLocation_Implementation。 -
服务器获取到该敌人Pawn的AIController(它只在服务器存在),并调用
MoveToLocation。 - 服务器的移动组件开始寻路并移动Pawn。
-
由于Pawn的
bReplicates=true且移动组件设置了复制,Pawn的位置变化会自动同步给所有客户端。 - 所有客户端上的该敌人Pawn更新位置,玩家就看到敌人移动了。
5. 避坑指南与高频面试问题解析
理论结合实践后,我们来直面那些最让人头疼的问题和面试官最爱挖的坑。
5.1 坑一:客户端调用MoveToLocation没反应(论坛问题重现)
问题
:就像开头论坛帖子说的,在客户端生成的AIController上调用
MoveToLocation
,AI不动。
根因
:
- 导航网格缺失 :客户端的关卡里可能根本没有生成导航网格(NavMesh)。导航是服务器端的行为,客户端默认不关心。你需要确保客户端也有导航数据。在UE编辑器中,检查导航网格边界体积(Nav Mesh Bounds Volume)是否覆盖了区域,并确保在项目设置中勾选了“Allow Client Side Navigation”。但即使勾选,在打包后客户端也可能需要手动加载导航数据,这很复杂。
-
AIController的归属
:即使客户端有导航,你手动在客户端生成的AIController,它控制的Pawn可能是一个“副本”,而不是服务器权威的那个Pawn。你移动了这个“副本”,但服务器的权威状态没变,下一秒就被同步覆盖了。
解决方案
:
99%的情况,你不应该这样做。
回归到服务器权威模式。如果必须是客户端本地特效AI,确保:
- 项目设置中开启“Allow Client Side Navigation”。
-
在客户端关卡开始时,手动调用
FNavigationSystem::Create<UNavigationSystemV1>(GetWorld())来创建导航系统,并强制构建导航网格(这有性能开销)。 -
这个AI Pawn的
bReplicates必须为false,避免与服务器Pawn冲突。
5.2 坑二:RPC没执行,调试发现根本没触发
问题
:打了断点,发现Client RPC或Server RPC的实现函数(
_Implementation
)没有被调用。
排查清单
:
-
UFUNCTION宏检查
:是否漏写了
Server、Client、Reliable等关键字?宏是否拼写正确? -
执行权限检查
:
-
ServerRPC必须从客户端调用。在服务器上直接调用ServerXXX()函数,它只会本地执行,不会走网络。用HasAuthority()判断。 -
ClientRPC必须从服务器调用,并且 该Actor必须有一个网络拥有者(Net Owner) 。这是最常被忽略的!一个由服务器拥有的AIController,调用ClientRPC()是无效的,因为找不到对应的客户端。你需要通过PlayerController或玩家Pawn来调用。
-
-
连接性检查
:确保网络连接已经建立(
GetNetMode() != NM_Standalone),并且Actor的Role正确(服务器上ROLE_Authority,客户端上ROLE_SimulatedProxy或ROLE_AutonomousProxy)。 -
复制设置检查
:调用RPC的Actor,其类必须被注册为可复制的(在
GetLifetimeReplicatedProps中有属性复制,或者本身是bReplicates=true的Actor)。一个纯本地(非复制)的Actor不能发送RPC。
5.3 坑三:移动同步延迟大,AI在客户端“瞬移”或“抖动”
问题 :服务器AI移动平滑,但客户端看到的AI一卡一卡的。 原因与优化 :
-
网络更新频率过低
:检查AI Pawn的
NetUpdateFrequency。默认值可能较低。适当提高(如从2调到5-10),但注意带宽和性能。 -
移动组件压缩
:
CharacterMovementComponent使用ReplicatedMovement结构体同步,它会对位置、旋转、速度进行量化压缩以减少带宽。在CharacterMovementComponent细节面板中,可以调整位置和旋转的复制精度,精度越高带宽消耗越大。 -
考虑插值(Interpolation)
:客户端收到新的位置后,不是直接“跳”过去,而是平滑地移动过去。UE的移动同步本身带有插值。你可以调整AI Pawn的
NetUpdateFrequency和MinNetUpdateFrequency来平衡及时性与平滑性。也可以自定义ReplicatedMovement的插值逻辑,但这属于高级话题。 - 服务器帧率与移动计算 :确保服务器有稳定的帧率。如果服务器卡顿,移动计算慢,同步出来的位置自然不连贯。
5.4 面试高频问题集锦与回答思路
Q1:AIController需要设置
bReplicates = true
吗?为什么?
A1
:绝大多数情况下不需要。AIController是纯逻辑实体,其状态(如当前目标、行为树状态)如果不需要客户端知晓,就不应复制。客户端只需要看到它控制的结果(Pawn的移动和动画)。复制AIController会浪费带宽,并可能暴露不必要的逻辑给客户端,增加安全风险。只有在极少数需要客户端知晓AI决策状态(如显示AI意图给玩家)时,才考虑有选择地复制部分属性。
Q2:如何在服务器上让AI移动,并在所有客户端播放移动开始的音效? A2 :这是一个经典的RPC组合应用。
-
在服务器AIController的
MoveToLocation调用之后, 在AI Pawn上 调用一个NetMulticastRPC,例如Multicast_PlayMoveSound()。 -
为什么在Pawn上?因为Pawn在所有客户端都存在(
bReplicates=true),是执行播放音效这类表现逻辑的合适载体。 -
在
Multicast_PlayMoveSound_Implementation里,编写播放音效的代码。由于是NetMulticast,它会在服务器和所有客户端执行。
Q3:如果AI的移动需要非常高的响应速度(如格斗游戏的AI),有什么架构建议? A3 :这需要权衡一致性和响应性。
- 首选 :依然是服务器权威。但可以优化网络传输,使用UDP(Unreliable)同步非关键移动状态,提高频率。同时,服务器AI的决策逻辑要足够高效。
- 高阶方案 :采用“服务器决策-客户端执行”的混合模式(场景四)。服务器只发送高级指令(“攻击玩家A”),客户端AI根据指令进行本地寻路和移动。服务器通过关键帧(如每0.5秒)同步一次权威位置进行校验和修正。这需要设计一套复杂的指令集和状态同步协议,开发难度大,且抗作弊能力减弱。
- 强调 :向面试官说明,没有银弹,需要根据游戏类型、AI复杂度、安全要求来具体选择。对于大多数游戏,服务器权威是更稳妥的选择。
Q4:
MoveToLocation
是一个RPC吗?它的网络行为是怎样的?
A4
:
MoveToLocation
不是
一个RPC。它是
AAIController
的一个本地函数。它的网络行为取决于调用它的AIController在哪里。
- 如果它在 服务器 的AIController上被调用,那么移动计算在服务器进行,移动结果通过Pawn的位置属性同步到客户端。
- 如果它在 客户端 的AIController上被调用,那么它只尝试进行客户端本地的导航和移动,这个移动不会被同步到服务器,也通常不被允许(除非是纯客户端特效AI)。
-
所以,让AI移动的核心,是
确保
MoveToLocation在服务器上有权限的AIController上被调用 。我们通常通过一个从客户端发起的Server RPC来“请求”服务器执行这个调用。
6. 调试技巧与性能考量
理论、实践、避坑都讲了,最后分享一些让开发过程更顺畅的“软技能”。
6.1 网络调试可视化
UE4内置了强大的网络调试工具,一定要善用。
-
stat net:在游戏运行时控制台输入,查看网络流量、更新频率、RPC调用次数等核心数据。关注In/Out Bunch和In/Out RPC。 -
showdebug ai:显示AI的当前状态、行为树执行路径、感知刺激等,对于调试AI逻辑是否在正确端执行至关重要。 -
visualize replication:在编辑器偏好设置中开启,或在控制台输入相关命令,可以高亮显示正在被复制的Actor和属性,一眼看出哪个Actor没被复制。 -
Network Profiler
:通过
~打开控制台,输入NetProfile,可以启动一个更详细的网络性能分析器,记录和分析每一帧的网络活动。
6.2 性能优化点
当你的游戏里有上百个AI时,网络同步会成为性能瓶颈。
-
降低更新频率
:不是所有AI都需要高频更新。远处的、非战斗状态的AI,可以将其
NetUpdateFrequency和NetPriority设低。 -
距离相关性更新
:实现自定义的
IsNetRelevantFor函数,根据观察者(玩家)与AI的距离来决定是否复制以及复制频率。UE本身有距离衰减,但你可以做得更精细。 -
属性复制优化
:只复制必要的属性。如果一个属性不常变化,不要用
Replicated标记,改用RPC在变化时通知。 - AI逻辑的服务器负载 :复杂的AI行为树、环境查询(EQS)会消耗大量CPU。考虑使用异步查询、将AI逻辑分散到多帧执行、或者对非活跃AI使用简化的“休眠”逻辑。
6.3 一个完整的检查清单
当你遇到AI网络同步问题时,按这个清单从上到下排查:
-
[ ] AI Pawn的
bReplicates是否设置为true? -
[ ] AI Pawn的移动组件是否调用了
SetIsReplicated(true)? -
[ ] AIController是否在服务器上生成并成功
Possess了AI Pawn?(检查服务器日志) -
[ ] 移动指令(如
MoveToLocation)是否确定在服务器端被执行?(在Server_MoveToLocation_Implementation中打日志或断点) -
[ ] 客户端是否能收到AI Pawn的位置更新?(使用
visualize replication查看) - [ ] 如果用了RPC,RPC的宏(Server/Client/Reliable)是否正确?调用端和执行端是否符合规则?
- [ ] 项目设置中,网络相关选项(如“Enable Actor Replication”)是否开启?
把这些点吃透,你在UE4网络面试中关于AIController和RPC的部分,就能从“被动回答”变为“主动输出”,向面试官展示你不仅知道是什么,更知道为什么,以及在实际项目中如何权衡和落地。这正是一个资深开发者与初级工程师的核心区别所在。
212

被折叠的 条评论
为什么被折叠?



