这个文章主要讲控制器类的作用;
我会系统梳理 UE 中APlayerController(玩家控制器)能做的所有核心操作,这是理解 UE 玩家输入 / 控制逻辑的关键。我会按功能分类,用 "大白话 + 核心 API + 使用场景" 的形式,把玩家控制器的能力讲得清晰易懂,新手也能快速掌握。
核心前提(先明确)
APlayerController是 UE 中 "玩家和游戏世界交互的核心枢纽",所有和 "玩家输入、视角、控制对象、UI 交互" 相关的操作,几乎都由它负责。它的核心定位:玩家的 "总遥控器"+"感知中枢"。
一、输入相关操作(最核心)
玩家控制器是处理所有玩家输入的 "入口",也是你之前代码中用到的核心能力。
| 核心操作 | 关键 API | 大白话解释 | 典型场景 |
|---|---|---|---|
| 1. 获取鼠标光标碰撞点 | GetHitResultUnderCursor() |
把屏幕 2D 光标位置转成 3D 世界碰撞点 | 坦克瞄准、点击拾取物品、鼠标交互 UI / 世界物体 |
| 2. 绑定输入动作(新版) | UEnhancedInputComponent->BindAction() |
把输入映射上下文(IMC)里的动作绑定到函数(如 "Jump" 绑定到跳跃函数) | 玩家移动、开火、跳跃等所有按键 / 手柄操作 |
| 3. 绑定输入轴(旧版) | InputComponent->BindAxis() |
绑定轴向输入(如 WASD 对应移动轴、鼠标移动对应视角轴) | 角色移动、视角旋转(旧版输入系统) |
| 4. 禁用 / 启用输入 | SetInputMode() / EnableInput() / DisableInput() |
控制玩家是否能输入(比如暂停菜单时禁用游戏输入,只允许 UI 输入) | 暂停菜单、过场动画、UI 交互时锁定输入 |
| 5. 获取按键状态 | IsInputKeyDown() / WasInputKeyJustPressed() |
检测某个按键是否按住 / 刚按下 | 长按开火、按键连点检测 |
| 6. 设置输入模式 | SetInputModeGameAndUI() / SetInputModeUIOnly() |
切换输入模式(只游戏 / 只 UI / 游戏 + UI) | 打开 UI 时让鼠标显示并能点按钮,同时保留游戏输入 |
示例代码(核心输入操作):
cpp
// 1. 绑定输入动作(新版增强输入)
void AMyPlayerController::SetupInputComponent()
{
Super::SetupInputComponent();
if (UEnhancedInputComponent* EnhancedInputComp = Cast<UEnhancedInputComponent>(InputComponent))
{
// 绑定"移动"动作到处理函数
EnhancedInputComp->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyPlayerController::HandleMove);
// 绑定"开火"动作到处理函数
EnhancedInputComp->BindAction(FireAction, ETriggerEvent::Started, this, &AMyPlayerController::HandleFire);
}
}
// 2. 禁用游戏输入,只允许UI输入(打开暂停菜单时)
void AMyPlayerController::OpenPauseMenu()
{
FInputModeUIOnly InputMode;
InputMode.SetWidgetToFocus(PauseMenuWidget->TakeWidget()); // 聚焦到暂停菜单UI
SetInputMode(InputMode);
bShowMouseCursor = true; // 显示鼠标光标
}
二、控制 Pawn / 角色(核心职责)
玩家控制器的核心作用是 "控制 Pawn(坦克 / 角色)",负责建立 / 解除控制关系,以及传递指令。
| 核心操作 | 关键 API | 大白话解释 | 典型场景 |
|---|---|---|---|
| 1. 控制 Pawn | Possess() / UnPossess() |
绑定 / 解除和 Pawn 的控制关系(遥控器绑定 / 解绑坦克) | 玩家出生控制角色、切换控制单位(比如切换坦克 / 飞机) |
| 2. 获取当前控制的 Pawn | GetPawn() / GetPawn<ATank>() |
获取当前控制的角色 / 坦克(类型安全转换) | 给控制的坦克发 "开火" 指令、获取坦克位置 |
| 3. 切换控制的 Pawn | Possess(NewPawn) |
切换控制对象(比如玩家从坦克切换到步兵) | 载具切换、角色切换 |
| 4. 强制 Pawn 移动 / 转向 | ClientSetLocation() / SetControlRotation() |
强制控制的 Pawn 移动到指定位置 / 转向指定方向 | 传送玩家、剧情强制转向 |
示例代码(控制 Pawn):
cpp
// 1. 出生时控制默认角色
void AMyPlayerController::BeginPlay()
{
Super::BeginPlay();
// 生成角色并控制
AMyCharacter* SpawnedCharacter = GetWorld()->SpawnActor<AMyCharacter>(CharacterClass, SpawnPos, SpawnRot);
Possess(SpawnedCharacter); // 绑定控制关系
}
// 2. 切换控制的坦克
void AMyPlayerController::SwitchToTank(ATank* NewTank)
{
UnPossess(); // 先解绑当前控制的角色
Possess(NewTank); // 绑定新坦克
}
三、视角 / 相机控制(玩家视觉)
玩家控制器负责管理玩家的视角和相机,决定玩家 "看到什么"。
| 核心操作 | 关键 API | 大白话解释 | 典型场景 |
|---|---|---|---|
| 1. 设置控制旋转 | SetControlRotation() |
强制设置玩家的视角旋转(比如剧情强制看某个方向) | 过场动画、提示玩家看目标点 |
| 2. 获取 / 设置相机位置 | GetPlayerViewPoint() |
获取当前玩家的相机位置和旋转(视角原点) | 发射子弹(从相机位置射线检测)、第三人称视角计算 |
| 3. 启用 / 禁用鼠标视角 | bShowMouseCursor / bEnableMouseOverEvents |
显示 / 隐藏鼠标、启用鼠标悬停事件 | UI 交互时显示鼠标,游戏时隐藏 |
| 4. 设置鼠标灵敏度 | SetMouseSensitivity() |
调整鼠标视角旋转的灵敏度 | 游戏设置里的灵敏度调节 |
| 5. 锁定视角 | SetViewTarget() |
切换相机视角目标(比如切到固定相机、第三人称→第一人称) | 剧情相机、视角切换 |
示例代码(视角控制):
cpp
// 1. 获取玩家相机位置(用于发射射线)
FVector CameraLocation;
FRotator CameraRotation;
GetPlayerViewPoint(CameraLocation, CameraRotation); // 获取相机位置和旋转
// 2. 剧情强制让玩家看向某个目标点
void AMyPlayerController::LookAtTarget(FVector TargetPos)
{
FRotator LookAtRot = UKismetMathLibrary::FindLookAtRotation(GetPawn()->GetActorLocation(), TargetPos);
SetControlRotation(LookAtRot); // 强制视角转向目标
}
四、UI/HUD 相关操作
玩家控制器是连接玩家和 UI 的桥梁,负责管理 HUD、弹窗、UI 输入等。
| 核心操作 | 关键 API | 大白话解释 | 典型场景 |
|---|---|---|---|
| 1. 创建 / 销毁 HUD | CreateHUD() / GetHUD() |
创建玩家专属的 HUD(血条、弹药显示) | 每个玩家有独立的 HUD(双人同屏) |
| 2. 显示 UI 弹窗 | ShowNotification() / 蓝图中创建 Widget |
显示提示弹窗、加载界面、菜单 | 击杀提示、任务完成弹窗 |
| 3. 设置鼠标焦点 | SetWidgetToFocus() |
让鼠标聚焦到某个 UI 控件(比如输入框) | 登录界面、聊天输入框 |
| 4. 启用鼠标悬停事件 | bEnableMouseOverEvents |
让 UI 响应鼠标悬停(比如按钮高亮) | 所有 UI 交互场景 |
五、网络 / 多人游戏相关(进阶)
在多人游戏中,玩家控制器是 "本地玩家" 和 "服务器" 交互的核心,每个玩家有独立的控制器。
| 核心操作 | 关键 API | 大白话解释 | 典型场景 |
|---|---|---|---|
| 1. 判断是否是本地玩家 | IsLocalPlayerController() |
区分本地 / 远程控制器(多人游戏中只处理本地输入) | 多人游戏中避免远程玩家执行本地逻辑 |
| 2. 服务器 RPC 调用 | Server_XXX() / Client_XXX() |
向服务器 / 客户端发送指令(比如开火指令同步) | 多人游戏中同步玩家操作 |
| 3. 获取玩家 ID | GetPlayerId() / GetUniqueID() |
获取玩家的唯一标识(用于存档、排行榜) | 玩家数据存储、多人游戏身份识别 |
示例代码(多人游戏判断):
cpp
// 多人游戏中,只处理本地玩家的输入
void AMyPlayerController::HandleFire()
{
if (!IsLocalPlayerController()) return; // 非本地玩家不执行
Server_Fire(); // 向服务器发送开火指令
}
// 服务器端处理开火(RPC)
UFUNCTION(Server, Reliable)
void AMyPlayerController::Server_Fire()
{
// 服务器验证并执行开火逻辑
ATank* ControlledTank = GetPawn<ATank>();
if (ControlledTank) ControlledTank->Fire();
}
六、其他实用操作(高频)
| 核心操作 | 关键 API | 大白话解释 | 典型场景 |
|---|---|---|---|
| 1. 暂停 / 继续游戏 | SetPause() / ClearPause() |
暂停游戏(仅服务器 / 本地玩家能操作) | 暂停菜单、游戏暂停功能 |
| 2. 传送玩家 | TeleportTo() |
把控制的 Pawn 传送到指定位置 | 快速旅行、复活传送 |
| 3. 播放音效 / 震动 | ClientPlaySound() / ClientPlayHapticEffect() |
给玩家播放音效、手柄震动 | 击中反馈、开火震动、提示音效 |
| 4. 获取本地玩家 | GetLocalPlayer() |
关联到 ULocalPlayer(输入子系统载体) | 激活输入映射上下文(你之前的坦克代码) |
总结(核心能力速记)
APlayerController的核心能力可以归纳为 4 大类,新手记住这 4 点就够了:
- 输入处理:接收 / 解析玩家的键盘 / 鼠标 / 手柄输入,绑定到业务逻辑;
- 控制 Pawn:绑定 / 解绑控制的角色 / 坦克,传递操作指令;
- 视角管理:控制玩家的相机视角、鼠标显示 / 隐藏、输入模式;
- UI 交互:管理玩家的 HUD/UI,处理 UI 输入和鼠标交互。
额外关键点:
- 每个本地玩家对应一个
APlayerController(双人同屏时 Player0/Player1 各有一个); - 玩家控制器不负责 "角色移动 / 开火",只负责 "接收输入并告诉角色该移动 / 开火";
- 多人游戏中,只有本地玩家控制器处理输入,远程控制器只同步状态。
虚幻引擎_玩家控制器APlayerController(进阶)
https://mp.csdn.net/mp_blog/creation/editor/156986537