使用弹簧臂组件

弹簧臂组件用于自动控制摄像机被遮挡时的响应情况。

Choose your operating system:

Windows

macOS

Linux

选择实现方法:

Blueprints

C++

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

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

运行中的弹簧臂

你可以在本教程中使用自己的角色,前提是该角色已分配摄像机组件。如果你没有角色,建议你首先完成 使用摄像机组件 教程,创建本指南中使用的基本角色。

尽管可能无法消除摄像机中穿透关卡中对象的所有实例,但根据弹簧臂的设置,在摄像机被遮挡时自动移动摄像机的位置,然后在摄像机没有被遮挡时返回其默认位置,有助于减少它们。

创建弹簧臂组件

  1. 继续 使用摄像机组件 操作指南教程项目,打开 BP_CameraCharacter 蓝图。

  2. 组件(Components) 选项卡,点击 添加组件(Add Component) 按钮,然后搜索并选择 弹簧臂组件(Spring Arm Component) 。重命名组件为 SpringArmComp

    添加弹簧臂组件

  3. 组件(Components) 选项卡,将 CameraComp组件 拖放到 弹簧臂组件 进行连接。

    拖放摄像机组件到弹簧臂

  4. 组件(Components) 选项卡中选择 SpringArmComp**后,导航至 细节(Details) 面板。 弹簧臂组件** 有多种可用设置,如下所示。

    分段

    说明

    套接字(Sockets)

    提供将弹簧臂作为 骨骼网格体 套接字 上的 骨骼 父项的功能。

    摄像机(Camera)

    设置无碰撞时的弹簧臂长度,并设置 偏移

    摄像机碰撞(Camera Collision)

    设置是否检查碰撞,并定义检查碰撞的查询探针大小。

    摄像机设置(Camera Settings)

    设置是否从父级继承 Pitch Yaw Roll 使用Pawn控制旋转

    滞后(Lag)

    设置摄像机是否应落后于目标位置以及与滞后相关的设置。

  5. 变换(Transform) 类别,更改 位置(Location) 值为(0,0,150),然后更改 旋转(Rotation) 值为(0,0,90)。

    变换类别位置和旋转设置

  6. 摄像机设置(Camera Settings) 类别,点击 使用Pawn控制旋转(Use Pawn Control Rotation) 变量旁边的复选框,启用后 弹簧臂组件 的父项后将使用查看/控制Pawn(你的 CameraCharacter )的旋转。

    启用使用Pawn控制旋转复选框

  7. 滞后(Lag) 类别中,点击 启用摄像机滞后(Enable Camera Lag) 变量旁边的复选框,启用后摄像机将落后于目标位置,这将使运动更平稳。

    启用摄像机滞后复选框

  1. 继续 使用摄像机组件 操作指南教程项目,打开 CameraCharacter.h ,并在类定义中声明以下内容。

    UPROPERTY(EditDefaultsOnly,BlueprintReadWrite)
    class USpringArmComponent* SpringArmComp;
  2. 然后导航至 CameraCharacter.Cpp ,并包括以下类库。

    #include "GameFramework/SpringArmComponent.h"
  3. 接下来,在 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;
  4. 编译 你的代码。

  5. 内容浏览器(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;

设置角色输入

为了演示新实现弹簧臂组件的功能,你需要将移动输入添加到角色类中。

  1. 首先导航至 编辑(Edit)>项目设置(Project Settings)>引擎(Engine)>输入(Input) ,然后在 绑定(Bindings) 类别,点击 轴映射(Axis Mappings) 旁边的 + 号目标,创建新轴输入。

    项目设置轴映射

  2. 将此轴映射命名为 MoveForward ,然后从键映射菜单搜索并选择 W键值

    向前移动W键

  3. 点击 MoveForward轴映射(MoveForward Axis Mapping) 旁边的 + 号,添加额外键。从下拉菜单,搜索并选择 S键 ,然后设置 缩放(Scale) 值为 -1.0

    向前移动S键

  4. 点击 轴映射(Axis Mappings) 旁边的 + 号,创建新轴输入。将此输入命名为 MoveRight

    向右移动轴映射

  5. 点击 MoveRight轴映射(MoveRight Axis Mapping) 旁边的 + 号,创建额外键,然后设置 向右移动(Move Right) 键映射,使用值分别为 1.0 -1.0 D S 键 缩放,如下图所示。

    向右移动S和D键

  6. 绑定(Bindings) 类别,点击 轴映射(Axis Mappings) 旁边的 + 号,创建名为 Turn 的新输入,然后搜索并选择输入映射键的 鼠标X(Mouse X)

    绑定转动鼠标X

  7. 绑定(Bindings) 类别,点击 轴映射(Axis Mappings) 旁边的 + 号,创建名为 LookUp 的新输入,然后搜索并选择输入映射键的 鼠标Y(Mouse Y) ,将其 缩放(Scale) 值设置为 -1.0

    绑定查询鼠标负Y

  8. 然后,双击 BP_CameraCharacter ,并导航至 事件图表(Event Graph) ,右键点击图表,搜索并选择 输入轴事件(Input Axis Event) MoveForward

    点击查看大图

  9. 拖移 InputAxis Move Forward 节点的 执行(Execution) 引脚,在 下拉菜单 搜索并选择 Add Movement Input 节点,然后从 InputAxis Move Forward 节点拖移 轴值(Axis Value) 引脚,并连接到 Add Movement Input 节点的 缩放值(Scale Value) 引脚。

    点击查看大图

  10. 右键点击 事件图表(Event Graph) ,在 上下文菜单 搜索并选择 Get Control Rotation ,然后从 旋转体返回值(Rotator Return Value) 引脚拖移,并在 下拉菜单 搜索和选择 Break Rotator

    点击查看大图

  11. Break Rotator 节点,拖移 Z(Yaw) 引脚,在 下拉菜单 搜索并选择 Make Rotator 节点,然后,拖移 Make Rotator 节点的 旋转体返回值(Rotator Return Value) 引脚,在下拉菜单搜索并选择 获取向前矢量(Get Forward Vector)

    点击查看大图

  12. Get Forward Vector 节点,拖移 矢量返回值(Vector Return Value) 引脚,将其连接到 Add Movement Input 节点的 世界方向(World Direction) 引脚。

    点击查看大图

  13. 再次右键点击 事件图表(Event Graph) ,搜索并为你的 输入轴事件 选择 向右移动(Move Right)

    点击查看大图

  14. InputAxis MoveRight 节点拖移 执行(Execution) 引脚,在 下拉菜单 搜索并选择 Add Movement Input 节点,然后从 InputAxis MoveRight 节点连接 轴值(Axis Value) 引脚到 Add Movement Input 缩放值(Scale Value) 引脚。

    点击查看大图

  15. Make Rotator 节点,拖移 旋转体返回值(Rotator Return Value) 引脚,在 下拉菜单 搜索并选择 Get Right Vector 节点,然后拖移 矢量返回值(Vector Return Value) 引脚,并将其连接到 Add Movement Input 节点的 世界方向(World Direction) 引脚。

    点击查看大图

    已完成 移动输入事件 将如下图显示。

    点击查看大图

  16. 右键点击 事件图表(Event Graph) ,然后搜索并选择 InputAxis LookUp 事件节点,然后右键点击,搜索并选择 Add Controller Pitch Input 节点。

  17. InputAxis LookUp 节点的 Axis Value 引脚拖移,并连接到 Add Controller Pitch Input 节点的 Val 引脚。从 InputAxis LookUp 节点的 执行输出 引脚拖移,并连接到 Add Controller Pitch Input 节点的 执行输入 引脚。

    点击查看大图

  18. 右键点击 事件图表(Event Graph) ,然后搜索并选择 Input Axis Turn 事件节点,然后右键点击,搜索并选择Add Controller Yaw Input节点。

  19. Input Axis Turn 节点的 轴值(Axis Value) 引脚拖移,并连接到 Add Controller Yaw Input 节点的 Val 引脚。从 Input Axis Turn 节点的 执行输出 引脚拖移,并连接到 Add Controller Yaw Input 节点的 执行输入 引脚。

    点击查看大图

  20. 点击 编译 保存

    编译和保存

为了演示新实现弹簧臂组件的功能,你需要将移动输入添加到角色类中。

  1. 首先导航至 编辑(Edit)>项目设置(Project Settings)>引擎(Engine)>输入(Input) ,然后在 绑定(Bindings) 类别,点击 轴映射(Axis Mappings) 旁边的 + 号目标,创建新轴输入。

    项目设置轴映射

  2. 将此轴映射命名为 MoveForward ,然后从键映射菜单搜索并选择 W键值

    向前移动W键

  3. 点击 MoveForward轴映射(MoveForward Axis Mapping) 旁边的 + 号,添加额外键。从下拉菜单,搜索并选择 S键 ,然后设置 缩放(Scale) 值为 -1.0

    向前移动S键

  4. 点击 轴映射(Axis Mappings) 旁边的 + 号,创建新轴输入。将此输入命名为 MoveRight

    向右移动轴映射

  5. 点击 MoveRight轴映射(MoveRight Axis Mapping) 旁边的 + 号,创建额外键,然后设置 向右移动(Move Right) 键映射,使用值分别为 1.0 -1.0 D S 键 缩放,如下图所示。

    向右移动S和D键

  6. 绑定(Bindings) 类别,点击 轴映射(Axis Mappings) 旁边的 + 号,创建名为 Turn 的新输入,然后搜索并选择输入映射键的 鼠标X(Mouse X)

    绑定转动鼠标X

  7. 绑定(Bindings) 类别,点击 轴映射(Axis Mappings) 旁边的 + 号,创建名为 LookUp 的新输入,然后搜索并选择输入映射键的 鼠标Y(Mouse Y) ,将其 缩放(Scale) 值设置为 -1.0

    绑定查询鼠标负Y

  8. 然后,在 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);
        }
    }
  9. 接下来导航至 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逻辑。

关卡设置

要演示弹簧臂组件的功能,你需要在关卡中放置一些几何障碍物。

  1. 编辑器(Editor) 中,导航至 窗口(Window)>(放置Acotr(Place Actors) ,打开 放置Actors(Place Actors) 面板。

  2. 放置Actor(Place Actors) 面板,选择 几何体(Geometry) 选项卡,将 盒体笔刷(Box Brush) 拖放至关卡中。

    点击查看大图

  3. 细节(Details) 面板中,你可以导航至 笔刷设置(Brush Settings) 类别,调整 盒体笔刷(Box Brush) 的边界,并调整 X Y Z 值。

    点击查看大图

  4. 然后,从 工具栏(Toolbar) ,按 在编辑器中运行(PIE(Play In Editor))

    在编辑器中运行工具栏

最终结果

弹簧臂演示

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

欢迎帮助改进虚幻引擎文档!请告诉我们该如何更好地为您服务。
填写问卷调查
取消