在此操作指南教程中,你将添加弹簧臂组件,并将其作为 摄像机组件 的父项。弹簧臂组件为你的摄像机提供功能,使其可以根据Gameplay情况进行扩展或回缩。通常,你可能希望向角色添加摄像机,以便创建第三人称视角。通常建议采用弹簧臂,以便自动控制摄像机如何处理被关卡几何体或其他对象遮挡的情况。
在此操作指南教程中,你将添加 弹簧臂组件 (USpringArmComponent),并将其作为 摄像机组件 的父项。弹簧臂组件为你的摄像机提供功能,使其可以根据Gameplay情况进行扩展或回缩。通常,你可能希望向角色添加摄像机,以便创建第三人称视角。通常建议采用弹簧臂,以便自动控制摄像机如何处理被关卡几何体或其他对象遮挡的情况。

你可以在本教程中使用自己的角色,前提是该角色已分配摄像机组件。如果你没有角色,建议你首先完成使用摄像机组件教程,创建本指南中使用的基本角色。
尽管可能无法消除摄像机中穿透关卡中对象的所有实例,但根据弹簧臂的设置,在摄像机被遮挡时自动移动摄像机的位置,然后在摄像机没有被遮挡时返回其默认位置,有助于减少它们。
创建弹簧臂组件
-
继续使用摄像机组件操作指南教程项目,打开 BP_CameraCharacter 蓝图。
-
在 组件(Components) 选项卡,点击 添加组件(Add Component) 按钮,然后搜索并选择 弹簧臂组件(Spring Arm Component)。重命名组件为 SpringArmComp。
-
在 组件(Components) 选项卡,将 CameraComp组件 拖放到 弹簧臂组件 进行连接。
-
在 组件(Components) 选项卡中选择 SpringArmComp后,导航至 细节(Details) 面板。弹簧臂组件 有多种可用设置,如下所示。
分段 说明 套接字(Sockets) 提供将弹簧臂作为 骨骼网格体 或 套接字 上的 骨骼 父项的功能。 摄像机(Camera) 设置无碰撞时的弹簧臂长度,并设置 偏移。 摄像机碰撞(Camera Collision) 设置是否检查碰撞,并定义检查碰撞的查询探针大小。 摄像机设置(Camera Settings) 设置是否从父级继承 Pitch、Yaw 或 Roll 或 使用Pawn控制旋转。 滞后(Lag) 设置摄像机是否应落后于目标位置以及与滞后相关的设置。 -
在 变换(Transform) 类别,更改 位置(Location) 值为(0,0,150),然后更改 旋转(Rotation) 值为(0,0,90)。
-
在 摄像机设置(Camera Settings) 类别,点击 使用Pawn控制旋转(Use Pawn Control Rotation) 变量旁边的复选框,启用后 弹簧臂组件 的父项后将使用查看/控制Pawn(你的 CameraCharacter)的旋转。
-
在 滞后(Lag) 类别中,点击 启用摄像机滞后(Enable Camera Lag) 变量旁边的复选框,启用后摄像机将落后于目标位置,这将使运动更平稳。
- 继续使用摄像机组件操作指南教程项目,打开
CameraCharacter.h
,并在类定义中声明以下内容。
UPROPERTY(EditDefaultsOnly,BlueprintReadWrite)
class USpringArmComponent* SpringArmComp;
- 然后导航至
CameraCharacter.Cpp
,并包括以下类库。
#include "GameFramework/SpringArmComponent.h"
- 接下来,在 ACameraCharacter::ACameraCharacter 构造函数中,声明以下代码。
//实例化类组件
SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComp"));
//将你的弹簧臂附加到角色的骨骼网格体组件
SpringArmComp->SetupAttachment(GetMesh());
//将摄像机附加到SpringArmComponent
CameraComp->AttachToComponent(SpringArmComp, FAttachmentTransformRules::KeepRelativeTransform);
//设置SpringArmComp的默认属性
SpringArmComp->bUsePawnControlRotation = true;
SpringArmComp->bEnableCameraLag = true;
SpringArmComp->TargetArmLength = 300.0f;
-
编译 你的代码。
-
从 内容浏览器(Content Browser),双击 BP_CameraCharacter,打开 类默认值(Class Defaults),然后导航至 组件(Components) 选项卡,并选择 SpringArmComp。
[弹簧臂组件](API:USpringArmComponent)有多种设置,如下所示。
/** 弹簧臂末端的套接字名称(回看弹簧臂原点) */
static const FName SocketName;
/** 无碰撞时弹簧臂的自然长度 */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Camera)
float TargetArmLength;
/** 弹簧臂末端偏移;使用它而不是附加组件的相对偏移确保线路追踪能够按需运行 */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Camera)
FVector SocketOffset;
/** 弹簧起点偏移,应用于世界空间。如果你希望与父组件之间有一个世界空间偏移,而不是通常的相对空间偏移,请使用此选项。*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Camera)
FVector TargetOffset;
/** 查询探针球体应有多大(以虚幻为单位) */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraCollision, meta=(editcondition="bDoCollisionTest"))
float ProbeSize;
/** 查询探针的碰撞通道(默认为ECC_Camera) */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraCollision, meta=(editcondition="bDoCollisionTest"))
TEnumAsByte<ECollisionChannel> ProbeChannel;
/** 如果为true,请使用ProbeChannel和ProbeSize进行碰撞测试,防止将摄像机卡入关卡。 */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraCollision)
uint32 bDoCollisionTest:1;
/**如果将此组件放置在Pawn上,是否应尽可能使用Pawn的视图/控件旋转?
* 禁用后,该组件将恢复为使用该组件的存储RelativeRotation。**/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
uint32 bUsePawnControlRotation:1;
/** 如果我们从父组件继承pitch。如果使用绝对旋转,则不执行任何操作。*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
uint32 bInheritPitch : 1;
/** 如果我们从父组件继承Yaw。如果使用绝对旋转,则不执行任何操作。*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
uint32 bInheritYaw : 1;
/** 如果我们从父组件继承Roll。如果使用绝对旋转,则不执行任何操作。*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
uint32 bInheritRoll : 1;
/**
* 如果为true,则摄像机会落后于目标位置以便使移动平滑。
* @see CameraLagSpeed
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag)
uint32 bEnableCameraLag : 1;
/**
* 如果为true,则摄像机会落后于目标旋转以便使移动平滑。
* @see CameraRotationLagSpeed
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag)
uint32 bEnableCameraRotationLag : 1;
/**
* 如果bUseCameraLagSubstepping为true,则子步长摄像机衰减,以便它很好地处理波动的帧率(尽管这会产生开销)。
* @see CameraLagMaxTimeStep
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Lag, AdvancedDisplay)
uint32 bUseCameraLagSubstepping : 1;
/**
* 如果为true并且启用摄像机位置滞后,则在摄像机目标(绿色)和滞后位置(黄色)上绘制标记。
* 在两个位置之间绘制一条线,通常为绿色,如果到滞后目标的距离已被限制(通过CameraLagMaxDistance),则为红色。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag)
uint32 bDrawDebugLagMarkers : 1;
/** 如果bEnableCameraLag为true,则控制摄像机到达目标位置的速度。低值表示较慢(更多延迟),高值表示较快(更少延迟),而零为瞬时(没有延迟)。*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag, meta=(editcondition="bEnableCameraLag", ClampMin="0.0", ClampMax="1000.0", UIMin = "0.0", UIMax = "1000.0"))
float CameraLagSpeed;
/** 如果bEnableCameraRotationLag为true,则控制摄像机到达目标位置的速度。低值表示较慢(更多延迟),高值表示较快(更少延迟),而零为瞬时(没有延迟)。*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag, meta=(editcondition = "bEnableCameraRotationLag", ClampMin="0.0", ClampMax="1000.0", UIMin = "0.0", UIMax = "1000.0"))
float CameraRotationLagSpeed;
/** 当分步摄像机滞后时使用最大时间步长。*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Lag, AdvancedDisplay, meta=(editcondition = "bUseCameraLagSubstepping", ClampMin="0.005", ClampMax="0.5", UIMin = "0.005", UIMax = "0.5"))
float CameraLagMaxTimeStep;
/** 摄像机目标的最大距离可能会落后于当前位置。如果设置为零,则不强制执行最大距离。*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag, meta=(editcondition="bEnableCameraLag", ClampMin="0.0", UIMin = "0.0"))
float CameraLagMaxDistance;
设置角色输入
为了演示新实现弹簧臂组件的功能,你需要将移动输入添加到角色类中。
-
首先导航至 编辑(Edit)>项目设置(Project Settings)>引擎(Engine)>输入(Input),然后在 绑定(Bindings) 类别,点击 轴映射(Axis Mappings) 旁边的 + 号目标,创建新轴输入。
-
将此轴映射命名为 MoveForward,然后从键映射菜单搜索并选择 W键值。
-
点击 MoveForward轴映射(MoveForward Axis Mapping) 旁边的 + 号,添加额外键。从下拉菜单,搜索并选择 S键,然后设置 缩放(Scale) 值为 -1.0。
-
点击 轴映射(Axis Mappings) 旁边的 + 号,创建新轴输入。将此输入命名为 MoveRight。
-
点击 MoveRight轴映射(MoveRight Axis Mapping) 旁边的 + 号,创建额外键,然后设置 向右移动(Move Right) 键映射,使用值分别为 1.0 和 -1.0 的 D 和 S 键 缩放,如下图所示。
-
在 绑定(Bindings) 类别,点击 轴映射(Axis Mappings) 旁边的 + 号,创建名为 Turn 的新输入,然后搜索并选择输入映射键的 鼠标X(Mouse X)。
-
在 绑定(Bindings) 类别,点击 轴映射(Axis Mappings) 旁边的 + 号,创建名为 LookUp 的新输入,然后搜索并选择输入映射键的 鼠标Y(Mouse Y),将其 缩放(Scale) 值设置为 -1.0。
-
然后,双击 BP_CameraCharacter,并导航至 事件图表(Event Graph),右键点击图表,搜索并选择 输入轴事件(Input Axis Event) 的 MoveForward。
点击查看大图
-
拖移 InputAxis Move Forward 节点的 执行(Execution) 引脚,在 下拉菜单 搜索并选择 Add Movement Input 节点,然后从 InputAxis Move Forward 节点拖移 轴值(Axis Value) 引脚,并连接到 Add Movement Input 节点的 缩放值(Scale Value) 引脚。
点击查看大图
-
右键点击 事件图表(Event Graph),在 上下文菜单 搜索并选择 Get Control Rotation,然后从 旋转体返回值(Rotator Return Value) 引脚拖移,并在 下拉菜单 搜索和选择 Break Rotator。
点击查看大图
-
从 Break Rotator 节点,拖移 Z(Yaw) 引脚,在 下拉菜单 搜索并选择 Make Rotator 节点,然后,拖移 Make Rotator 节点的 旋转体返回值(Rotator Return Value) 引脚,在下拉菜单搜索并选择 获取向前矢量(Get Forward Vector)。
点击查看大图
-
从 Get Forward Vector 节点,拖移 矢量返回值(Vector Return Value) 引脚,将其连接到 Add Movement Input 节点的 世界方向(World Direction) 引脚。
点击查看大图
-
再次右键点击 事件图表(Event Graph),搜索并为你的 输入轴事件 选择 向右移动(Move Right)。
点击查看大图
-
从 InputAxis MoveRight 节点拖移 执行(Execution) 引脚,在 下拉菜单 搜索并选择 Add Movement Input 节点,然后从 InputAxis MoveRight 节点连接 轴值(Axis Value) 引脚到 Add Movement Input 的 缩放值(Scale Value) 引脚。
点击查看大图
-
从 Make Rotator 节点,拖移 旋转体返回值(Rotator Return Value) 引脚,在 下拉菜单 搜索并选择 Get Right Vector 节点,然后拖移 矢量返回值(Vector Return Value) 引脚,并将其连接到 Add Movement Input 节点的 世界方向(World Direction) 引脚。
点击查看大图
已完成 移动输入事件 将如下图显示。
点击查看大图
-
右键点击 事件图表(Event Graph),然后搜索并选择 InputAxis LookUp 事件节点,然后右键点击,搜索并选择 Add Controller Pitch Input 节点。
-
从 InputAxis LookUp 节点的 Axis Value 引脚拖移,并连接到 Add Controller Pitch Input 节点的 Val 引脚。从 InputAxis LookUp 节点的 执行输出 引脚拖移,并连接到 Add Controller Pitch Input 节点的 执行输入 引脚。
点击查看大图
-
右键点击 事件图表(Event Graph),然后搜索并选择 Input Axis Turn 事件节点,然后右键点击,搜索并选择Add Controller Yaw Input节点。
-
从 Input Axis Turn 节点的 轴值(Axis Value) 引脚拖移,并连接到 Add Controller Yaw Input 节点的 Val 引脚。从 Input Axis Turn 节点的 执行输出 引脚拖移,并连接到 Add Controller Yaw Input 节点的 执行输入 引脚。
点击查看大图
-
点击 编译 并 保存。
为了演示新实现弹簧臂组件的功能,你需要将移动输入添加到角色类中。
-
首先导航至 编辑(Edit)>项目设置(Project Settings)>引擎(Engine)>输入(Input),然后在 绑定(Bindings) 类别,点击 轴映射(Axis Mappings) 旁边的 + 号目标,创建新轴输入。
-
将此轴映射命名为 MoveForward,然后从键映射菜单搜索并选择 W键值。
-
点击 MoveForward轴映射(MoveForward Axis Mapping) 旁边的 + 号,添加额外键。从下拉菜单,搜索并选择 S键,然后设置 缩放(Scale) 值为 -1.0。
-
点击 轴映射(Axis Mappings) 旁边的 + 号,创建新轴输入。将此输入命名为 MoveRight。
-
点击 MoveRight轴映射(MoveRight Axis Mapping) 旁边的 + 号,创建额外键,然后设置 向右移动(Move Right) 键映射,使用值分别为 1.0 和 -1.0 的 D 和 S 键 缩放,如下图所示。
-
在 绑定(Bindings) 类别,点击 轴映射(Axis Mappings) 旁边的 + 号,创建名为 Turn 的新输入,然后搜索并选择输入映射键的 鼠标X(Mouse X)。
-
在 绑定(Bindings) 类别,点击 轴映射(Axis Mappings) 旁边的 + 号,创建名为 LookUp 的新输入,然后搜索并选择输入映射键的 鼠标Y(Mouse Y),将其 缩放(Scale) 值设置为 -1.0。
-
然后,在
CameraCharacter.cpp
中为 ACamerCharacter::MoveFoward 和 ACameraCharacter::MoveRight 类方法实现以下逻辑
void ACameraCharacter::MoveForward(float AxisValue)
{
if ((Controller != nullptr) && (AxisValue != 0.0f))
{
// 找出向前方向
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0, Rotation.Yaw, 0);
// 获取向前矢量
const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
AddMovementInput(Direction, AxisValue);
}
}
void ACameraCharacter::MoveRight(float AxisValue)
{
if ((Controller != nullptr) && (AxisValue != 0.0f))
{
// 找出向右方向
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0, Rotation.Yaw, 0);
// 获取向右矢量
const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
// 以该方向增加移动
AddMovementInput(Direction, AxisValue);
}
}
- 接下来导航至 ACameraCharacter::SetupPlayerInputComponent 方法,并实现以下代码。
//用于将功能绑定到输入
void ACameraCharacter::SetupPlayerInputComponent(UInputComponent*)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAxis("MoveForward",this, &ACameraCharacter::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &ACameraCharacter::MoveRight);
PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
}
角色 类继承至 Pawn 类。在此示例中,我们使用Pawn的AddControllerPitchInput和AddControllerYawInput类方法处理我们的Turn和LookUp逻辑。
关卡设置
要演示弹簧臂组件的功能,你需要在关卡中放置一些几何障碍物。
-
在 编辑器(Editor) 中,导航至 窗口(Window)>(放置Acotr(Place Actors),打开 放置Actors(Place Actors) 面板。
-
在 放置Actor(Place Actors) 面板,选择 几何体(Geometry) 选项卡,将 盒体笔刷(Box Brush) 拖放至关卡中。
点击查看大图
-
在 细节(Details) 面板中,你可以导航至 笔刷设置(Brush Settings) 类别,调整 盒体笔刷(Box Brush) 的边界,并调整 X、Y 和 Z 值。
点击查看大图
-
然后,从 工具栏(Toolbar),按 在编辑器中运行(PIE(Play In Editor))。
最终结果

使用 WASD 移动角色时,你将注意到摄像机略有落后于角色的移动。另外,当你在墙壁附近导航角色时,摄像机会试图重新定位自己,并移动靠近。当角色没有被遮挡时,弹簧臂返回摄像机至默认类属性中指定的默认 目标臂长度。