下面我将为你详细拆解,从最基础到最常用的方法,并提供关键步骤和代码示例。

核心概念:移动的本质
在UE中,物体的“移动”并不是简单地改变它的位置,它是一个复杂的过程,通常涉及以下几个核心组件:
-
角色/ pawn:
Character: 继承自Pawn,是专门为有生命、可以移动、有视角的实体设计的,它自带胶囊体碰撞、角色移动组件 和摄像机臂,这是制作第三人称或第一人称机器人最常用的基类。Pawn: 更通用的基类,可以是任何有控制权的物体,比如一辆坦克、一个炮塔,甚至一个可以远程控制的球体,它没有内置的移动逻辑。Actor: 最基础的类,它没有任何特殊功能,只是一个可以在世界中放置的物体,如果你想做一个完全自定义的移动系统(比如基于物理的移动),可以从Actor开始。
-
角色移动组件:
- 这是
Character的核心,它处理了所有与移动相关的逻辑,如行走、奔跑、跳跃、重力、与地面的关系等,你通常不需要直接修改它的源码,而是通过设置它的属性或调用它的函数来控制它。
- 这是
-
输入组件:
(图片来源网络,侵删)- 负责捕获玩家的输入(键盘、手柄、鼠标等),并将其转换为游戏内的动作(如“前进”、“后退”、“左转”)。
Character默认会为你创建一个输入组件。
- 负责捕获玩家的输入(键盘、手柄、鼠标等),并将其转换为游戏内的动作(如“前进”、“后退”、“左转”)。
使用蓝图 - 最快、最直观的方法
对于初学者和快速原型制作,蓝图是最佳选择,这里我们以最常见第三人称机器人为例。
步骤 1: 创建角色蓝图
浏览器中,右键 -> 蓝图表 -> 角色蓝图 (Blueprint Class)。
2. 在选择父类窗口中,搜索并选择 ThirdPersonCharacter (如果你想做第一人称,就选 FirstPersonCharacter)。
3. 为你的蓝图命名,BP_Robot。
步骤 2: 设置输入
- 打开
BP_Robot,在 事件图表 中找到Event ActorBeginOverlap或Event BeginPlay节点,右键点击其输出引脚,搜索并添加Event Player Input Action。 - 在
Details面板中,为这个事件设置一个输入操作名称,设置MoveForward和MoveRight,你需要在项目的 设置 -> 输入 中提前配置好这些操作(默认WASD和方向键已经配置好了)。 - 重复以上步骤,添加用于
Turn(转向) 和Look(视角) 的事件。
步骤 3: 编写移动逻辑
- 从
Event Player Input Action (MoveForward)节点中,拖出Action Value引脚。 - 添加一个
Add Movement Input节点。- 将
Action Value连接到Scale输入。 - 在
World Direction输入,点击下拉箭头,选择Make Vector。 - 在
Make Vector节点中,将X输入设为Action Value,Y和Z设为0。 - 将
Add Movement Input节点的Target引脚留空(它会自动指向自身)。
- 将
- 对
Event Player Input Action (MoveRight)做同样的操作,但在Make Vector节点中,将Y输入设为Action Value。 - 对于转向,使用
Add Controller Yaw Input节点,将Turn事件的Action Value连接到它的输入。
运行游戏,你的机器人就可以用WASD移动了。
使用 C++ - 更灵活、更高效
对于需要高性能或复杂逻辑的项目,C++是更好的选择。

步骤 1: 创建 C++ 角色
- 在虚幻编辑器中,
工具->新建 C++ 类。 - 选择
Character作为父类。 - 命名你的类,
ARobot。 - Visual Studio 会自动打开并生成
ARobot.h和ARobot.cpp文件。
步骤 2: 设置输入映射
打开你的项目设置(Edit -> Project Settings),进入 Engine -> Input -> Action Mappings,在这里添加或确认你需要的输入映射,
IA_MoveForward:绑定W和S。IA_MoveRight:绑定A和D。IA_Turn:绑定鼠标X轴。
步骤 3: 在 C++ 中实现移动
ARobot.h (头文件)
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Robot.generated.h"
UCLASS()
class YOURPROJECT_API ARobot : public ACharacter
{
GENERATED_BODY()
public:
// 构造函数
ARobot();
protected:
// 游戏开始时或玩家生成时调用
virtual void BeginPlay() override;
public:
// 每一帧调用
virtual void Tick(float DeltaTime) override;
// 绑定输入
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
private:
// 处理前后移动
void MoveForward(float Value);
// 处理左右移动
void MoveRight(float Value);
// 处理视角/身体转向
void Turn(float Rate);
};
ARobot.cpp (源文件)
#include "Robot.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/CharacterMovementComponent.h" // 引入移动组件
ARobot::ARobot()
{
// 设置这个角色每帧调用 Tick()
PrimaryActorTick.bCanEverTick = true;
// 如果你不想要角色的默认旋转,可以取消下面这行的注释
// GetCharacterMovement()->bOrientRotationToMovement = true;
}
void ARobot::BeginPlay()
{
Super::BeginPlay();
}
void ARobot::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// 这是关键!将输入函数与输入映射绑定起来
void ARobot::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
// 绑定 "IA_MoveForward" 映射到 MoveForward 函数
PlayerInputComponent->BindAxis("IA_MoveForward", this, &ARobot::MoveForward);
// 绑定 "IA_MoveRight" 映射到 MoveRight 函数
PlayerInputComponent->BindAxis("IA_MoveRight", this, &ARobot::MoveRight);
// 绑定 "IA_Turn" 映射到 Turn 函数
PlayerInputComponent->BindAxis("IA_Turn", this, &ARobot::Turn);
}
void ARobot::MoveForward(float Value)
{
// 只在输入不为零时移动
if (Value != 0.0f)
{
// 获取控制器的旋转
FRotator Rotation = GetControlRotation();
// 只使用 Yaw (水平旋转) 来移动,忽略 Pitch 和 Roll
Rotation.Pitch = 0.0f;
Rotation.Roll = 0.0f;
// 获取前向向量
const FVector Direction = FRotationMatrix(Rotation).GetUnitAxis(EAxis::X);
// 添加移动输入
AddMovementInput(Direction, Value);
}
}
void ARobot::MoveRight(float Value)
{
if (Value != 0.0f)
{
FRotator Rotation = GetControlRotation();
Rotation.Pitch = 0.0f;
Rotation.Roll = 0.0f;
// 获取右向向量
const FVector Direction = FRotationMatrix(Rotation).GetUnitAxis(EAxis::Y);
AddMovementInput(Direction, Value);
}
}
void ARobot::Turn(float Rate)
{
// 添加控制器旋转输入
AddControllerYawInput(Rate);
}
编译代码后,你就可以在编辑器中将 ARobot 拖放到关卡中,它就能响应输入了。
其他高级移动方式
除了基于 Character 的传统移动,你还可以选择其他方式:
基于物理的移动
如果你的机器人需要模拟真实的物理效果(如推箱子、被击飞、在斜面上滑动),可以使用 Add Force。
- 实现方式:在你的
RobotActor 中添加一个Static Mesh组件和一个Rigidbody组件,在 Tick 事件中,根据输入计算一个力,然后使用Add Force节点(C++中是UPrimitiveComponent::AddForce())施加到Rigidbody上。 - 优点:非常真实,物理效果丰富。
- 缺点:控制更复杂,难以实现精确的“走格子”或“FPS式”的移动。
简单的 Transform 移动
如果你只需要一个非常简单的移动,不关心碰撞或物理,可以直接修改 Actor 的位置和旋转。
- 实现方式:在 Tick 事件中,获取输入值,然后使用
Set Actor Location和Set Actor Rotation节点。 - 优点:最简单直接。
- 缺点:不推荐用于玩家控制的角色,因为它会忽略
CharacterMovementComponent提供的平滑、重力、地面检测等功能,移动会显得很生硬且不真实。
总结与建议
| 移动类型 | 推荐基类 | 核心组件 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|---|
| 标准角色移动 (人形/机器人) | Character |
CharacterMovementComponent |
功能完善、平滑、易用 | 灵活性相对较低 | 绝大多数机器人、NPC、玩家角色 |
| 自定义/物理移动 | Pawn 或 Actor |
UStaticMeshComponent + UPrimitiveComponent |
完全自由,可实现任何效果 | 需要自己实现所有逻辑 | 坦克、飞行器、载具、球体、需要特殊物理效果的角色 |
| 简单平移/旋转 | Actor |
无 | 代码量最少 | 功能弱,不真实 | 简单的UI动画、非交互性移动物体 |
给你的建议:
- 如果你是初学者:直接使用蓝图和
ThirdPersonCharacter,这是最快上手并看到效果的方法。 - 如果你想制作一个标准的机器人:使用C++继承
Character类,这是最规范、性能最好的方式。 - 如果你的机器人是坦克或飞船:考虑从
Pawn或Actor开始,并使用物理或自定义的移动逻辑。
标签: UDK机器人移动控制实现方法 UDK机器人移动控制编程教程 UDK机器人移动控制代码示例