Choose your operating system:
Windows
macOS
Linux
选择实现方法:
Blueprints
C++
在此操作指南教程中,你将添加 弹簧臂组件 ,并将其作为 摄像机组件 的父项。弹簧臂组件为你的摄像机提供功能,使其可以根据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 。
弹簧臂组件 有多种设置,如下所示。
/** 弹簧臂末端的套接字名称(回看弹簧臂原点) */ 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 移动角色时,你将注意到摄像机略有落后于角色的移动。另外,当你在墙壁附近导航角色时,摄像机会试图重新定位自己,并移动靠近。当角色没有被遮挡时,弹簧臂返回摄像机至默认类属性中指定的默认 目标臂长度 。