Using Spring Arm Components

The Spring Arm component is used to automatically control how the camera handles situations where it becomes obstructed.

Windows
MacOS
Linux

Choose your implementation method:

Blueprints

C++

In this How-to tutorial, you will add a Spring Arm Component and parent it to a Camera Component. Spring Arm Components provide functionality to your camera so that it can expand or retract based on gameplay situations. Oftentimes, you may wish to add a camera to a character for the purposes of creating a third person perspective. It is usually recommended to include a Spring Arm to automatically control how the camera handles situations where it becomes obstructed by level geometry or other objects.

In this How-to tutorial, you will add a Spring Arm Component (USpringArmComponent) and parent it to a Camera Component. Spring Arm Components provide functionality to your camera so that it can expand or retract based on gameplay situations. Oftentimes, you may wish to add a camera to a character for the purposes of creating a third person perspective. It is usually recommended to include a Spring Arm to automatically control how the camera handles situations where it becomes obstructed by level geometry or other objects.

Spring Arm in action

You can use your own character for this tutorial provided it has a Camera Component assigned to it. If you do not have a character, it is recommended that you first complete the Working with Camera Components tutorial in order to create the basic character being used in this guide.

While it may not eliminate all instances of the camera penetrating objects in your level, depending on your Spring Arm's settings, it will help reduce them by automatically moving the camera's position when it becomes obstructed and then returning to its default position when it is free from obstruction.

Creating the Spring Arm Component

  1. Continuing from the Working with Camera Components How-to tutorial project, open your BP_CameraCharacter Blueprint.

  2. In the Components tab, click the Add Component button then search and select the Spring Arm Component. Rename your component SpringArmComp.

    Add Spring Arm Component

  3. Inside the Components tab, drag your CameraComp Component onto the Spring Arm Component to attach it.

    Drag Camera Component on to Spring Arm

  4. With the SpringArmComp selected in the Components tab, navigate to the Details panel. There are multiple settings that can be used with the Spring Arm Component which are outlined below.

    Section

    Description

    Sockets

    Provide the capability to parent the Spring Arm to a Bone on a Skeletal Mesh or a Socket.

    Camera

    Set the length of the Spring Arm when there are no collisions as well as set Offsets.

    Camera Collision

    Set whether or not to check for collisions and define how big the query probe is to check for collisions.

    Camera Settings

    Set whether or not to inherit Pitch, Yaw, or Roll from the Parent or Use Pawn Control Rotation.

    Lag

    Set whether or not the camera should lag behind the target position and settings associated with lag.

  5. In the Transform category, change the Location value to (0,0,150), then change the Rotation value to (0,0,90).

    Transform category Location and Rotation settings

  6. In the Camera Settings category, click the checkbox beside the Use Pawn Control Rotation variable, when enabled the Spring Arm Component's parent will use the view/control rotation of the pawn (your CameraCharacter).

    Enable Use Pawn Control Rotation checkbox

  7. In the Lag category, click the checkbox beside the Enable Camera Lag variable, when enabled the camera will lag behind the target position which will result in a smoother movement.

    Enable Camera Lag checkbox

  1. Continuing from the Working with Camera Components How-to tutorial project, open your CameraCharacter.h, and declare the following in the class definition.

    UPROPERTY(EditDefaultsOnly,BlueprintReadWrite)
    class USpringArmComponent* SpringArmComp;
  2. Then navigate to CameraCharacter.Cpp, and include the following class library.

    #include "GameFramework/SpringArmComponent.h"
  3. Next, in your ACameraCharacter::ACameraCharacter constructor declare the following code.

    //Instantiating Class Components
    SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComp"));
    
    //Attach the Spring Arm to the Character's Skeletal Mesh Component
    SpringArmComp->SetupAttachment(GetMesh());
    
    //Attach the Camera to the SpringArmComponent
    CameraComp->AttachToComponent(SpringArmComp, FAttachmentTransformRules::KeepRelativeTransform);
    
    //Setting default properties of the SpringArmComp
    SpringArmComp->bUsePawnControlRotation = true;
    SpringArmComp->bEnableCameraLag = true;
    SpringArmComp->TargetArmLength = 300.0f;
  4. Compile your code.

  5. From the Content Browser, double-click your BP_CameraCharacter to open it's Class Defaults, then navigate to the Components tab, and select your SpringArmComp.

    There are multiple settings that can be used with the Spring Arm Component which are outlined below.

    /** The name of the socket at the end of the spring arm (looking back towards the spring arm origin) */
    
    static const FName SocketName;
    
    /** Natural length of the spring arm when there are no collisions */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Camera)
        float TargetArmLength;
    
        /** offset at end of spring arm; use this instead of the relative offset of the attached component to ensure the line trace works as desired */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Camera)
        FVector SocketOffset;
    
        /** Offset at the start of the spring, applied in world space. Use this if you want a world-space offset from the parent component instead of the usual relative-space offset. */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Camera)
        FVector TargetOffset;
    
    /** How big should the query probe sphere be (in unreal units) */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraCollision, meta=(editcondition="bDoCollisionTest"))
        float ProbeSize;
    
        /** Collision channel of the query probe (defaults to ECC_Camera) */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraCollision, meta=(editcondition="bDoCollisionTest"))
        TEnumAsByte<ECollisionChannel> ProbeChannel;
    
        /** If true, do a collision test using ProbeChannel and ProbeSize to prevent camera clipping into level.  */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraCollision)
        uint32 bDoCollisionTest:1;
    
    /**If this component is placed on a pawn, should it use the view/control rotation of the pawn where possible?
         * When disabled, the component will revert to using the stored RelativeRotation of the component.**/
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
        uint32 bUsePawnControlRotation:1;
    
        /** Should we inherit pitch from the parent component. Does nothing if using Absolute Rotation. */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
        uint32 bInheritPitch : 1;
    
        /** Should we inherit yaw from the parent component. Does nothing if using Absolute Rotation. */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
        uint32 bInheritYaw : 1;
    
        /** Should we inherit roll from the parent component. Does nothing if using Absolute Rotation. */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraSettings)
        uint32 bInheritRoll : 1;
    /**
         * If true, the camera lags behind the target position to smooth its movement.
         * @see CameraLagSpeed
         */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag)
        uint32 bEnableCameraLag : 1;
    
        /**
         * If true, the camera lags behind target rotation to smooth its movement.
         * @see CameraRotationLagSpeed
         */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag)
        uint32 bEnableCameraRotationLag : 1;
    
        /**
         * If bUseCameraLagSubstepping is true, sub-step camera damping so that it handles fluctuating frame rates well (though this comes at a cost).
         * @see CameraLagMaxTimeStep
         */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Lag, AdvancedDisplay)
        uint32 bUseCameraLagSubstepping : 1;
    
        /**
         * If true and camera location lag is enabled, draws markers at the camera target (in green) and the lagged position (in yellow).
         * A line is drawn between the two locations, in green normally but in red if the distance to the lag target has been clamped (by CameraLagMaxDistance).
         */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag)
        uint32 bDrawDebugLagMarkers : 1;
    
        /** If bEnableCameraLag is true, controls how quickly the camera reaches the target position. Low values are slower (more lag), high values are faster (less lag), while zero is instant (no lag). */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag, meta=(editcondition="bEnableCameraLag", ClampMin="0.0", ClampMax="1000.0", UIMin = "0.0", UIMax = "1000.0"))
        float CameraLagSpeed;
    
        /** If bEnableCameraRotationLag is true, controls how quickly the camera reaches the target position. Low values are slower (more lag), high values are faster (less lag), while zero is instant (no lag). */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag, meta=(editcondition = "bEnableCameraRotationLag", ClampMin="0.0", ClampMax="1000.0", UIMin = "0.0", UIMax = "1000.0"))
        float CameraRotationLagSpeed;
    
        /** Max time step used when sub-stepping camera lag. */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Lag, AdvancedDisplay, meta=(editcondition = "bUseCameraLagSubstepping", ClampMin="0.005", ClampMax="0.5", UIMin = "0.005", UIMax = "0.5"))
        float CameraLagMaxTimeStep;
    
        /** Max distance the camera target may lag behind the current location. If set to zero, no max distance is enforced. */
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag, meta=(editcondition="bEnableCameraLag", ClampMin="0.0", UIMin = "0.0"))
        float CameraLagMaxDistance;

Setting up Character Input

To demonstrate the functionality of your newly implemented Spring Arm Component, you will need to add movement input to your character class.

  1. Begin by navigating to Edit > Project Settings >Engine > Input, then in the Bindings category, click the + sign next to Axis Mappings to create a new Axis input.

    Project Settings Axis Mappings

  2. Name this Axis Mapping MoveForward, then search and select the W key value from the drop down key mapping menu.

    Move Forward W key

  3. Click the + sign next to the MoveForward Axis Mapping to add an additional key. From the drop down menu, search and select for the S key, then set the Scale value to -1.0.

    Move Forward S key

  4. Click the + sign next to Axis Mappings to create a new Axis input. Name this input MoveRight.

    Move RIght Axis Mapping

  5. Click the + sign next to the MoveRight Axis Mapping to create an additional key, and set up your Move Right key mappings and Scales using the D and S keys with values of 1.0 and -1.0 respectively, as shown in the image below.

    Move Right S and D keys

  6. In the Bindings category, click the + sign next to Axis Mappings to create a new input named Turn, then search and select Mouse X for the input mapping key.

    Binding Turn Mouse X

  7. In the Bindings category, click the + sign next to Axis Mappings to create a new input named LookUp, then search and select Mouse Y for the input mapping key, and set it's Scale value to -1.0.

    Binding Look Up Mouse negative Y

  8. Next, double click your BP_CameraCharacter and navigate to the Event Graph, right-click on the graph then search and select MoveForward for your Input Axis Event.

    Click image to enlarge

  9. Drag off the Execution pin of the InputAxis Move Forward node and in the drop down menu search for and select the Add Movement Input node, then drag off the Axis Value pin from the InputAxis Move Forward node and connect to the Scale Value pin of the Add Movement Input node.

    Click image to enlarge

  10. Right click on the Event Graph, in the context menu search for and select Get Control Rotation, then drag off from the Rotator Return Value pin and in the drop down menu search for and select Break Rotator.

    Click image to enlarge

  11. From the Break Rotator node, drag off the Z(Yaw) pin and in the drop down menu search for and select the Make Rotator node, then drag off the Rotator Return Value pin of the Make Rotator node and in the drop down menu search for and select Get Forward Vector.

    Click image to enlarge

  12. From the Get Forward Vector node, drag off the Vector Return Value pin and connect it to the Add Movement Input node's World Direction pin.

    Click image to enlarge

  13. Right-click on the Event Graph again and search for and select Move Right for your Input Axis Event.

    Click image to enlarge

  14. Drag off the Execution pin from your InputAxis MoveRight node and in the drop down menu search for and select for the Add Movement Input node, then connect the Axis Value pin from the InputAxis MoveRight node into the Scale Value pin of the Add Movement Input node.

    Click image to enlarge

  15. From the Make Rotator node, drag off the Rotator Return Value pin and in the drop down menu search for and select the Get Right Vector node, then drag off the Vector Return Value pin and connect it to the Add Movement Input node's World Direction pin.

    Click image to enlarge

    Your completed Movement Input Events will appear as shown in the image below.

    Click image to enlarge

  16. Right-click on the Event Graph, then search for and select the InputAxis LookUp event node, then right-click, search and select the Add Controller Pitch Input node.

  17. Drag off from the Axis Value pin of the InputAxis LookUp node and connect to the Val pin of the Add Controller Pitch Input node. Drag off the execution output pin of the InputAxis LookUp node and connect to the execution input pin of the Add Controller Pitch Input node.

    Click image to enlarge

  18. Right-click on the Event Graph, then search for and select the Input Axis Turn event node, then right-click, search, and select the Add Controller Yaw Input node.

  19. Drag off from the Axis Value pin of the Input Axis Turn node and connect to the Val pin of the Add Controller Yaw Input node. Drag off the execution output pin of the Input Axis Turn node and connect to the execution input pin of the Add Controller Yaw Input node.

    Click image to enlarge

  20. Click Compile and Save.

    Compile and Save

To demonstrate the functionality of your newly implemented Spring Arm Component, you will need to add movement input to your character class.

  1. Begin by navigating to Edit > Project Settings >Engine > Input, then in the Bindings category, click the + sign next to Axis Mappings to create a new Axis input.

    Project Settings Axis Mappings

  2. Name this Axis Mapping MoveForward, then search and select the W key value from the drop down key mapping menu.

    Move Forward W key

  3. Click the + sign next to the MoveForward Axis Mapping to add an additional key. From the drop down menu, search and select for the S key, then set the Scale value to -1.0.

    Move Forward S key

  4. Click the + sign next to Axis Mappings to create a new Axis input. Name this input MoveRight.

    Move RIght Axis Mapping

  5. Click the + sign next to the MoveRight Axis Mapping to create an additional key, and set up your Move Right key mappings and Scales using the D and S keys with values of 1.0 and -1.0 respectively, as shown in the image below.

    Move Right S and D keys

  6. In the Bindings category, click the + sign next to Axis Mappings to create a new input named Turn, then search and select Mouse X for the input mapping key.

    Binding Turn Mouse X

  7. In the Bindings category, click the + sign next to Axis Mappings to create a new input named LookUp, then search and select Mouse Y for the input mapping key, and set it's Scale value to -1.0.

    Binding Look Up Mouse negative Y

  8. Then in your CameraCharacter.cpp implement the following logic for your ACamerCharacter::MoveFoward, and ACameraCharacter::MoveRight class methods

    void ACameraCharacter::MoveForward(float AxisValue)
    {
        if ((Controller != nullptr) && (AxisValue != 0.0f))
        {
            // Find out which way is forward
            const FRotator Rotation = Controller->GetControlRotation();
            const FRotator YawRotation(0, Rotation.Yaw, 0);
    
            // Get forward vector
             const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
            AddMovementInput(Direction, AxisValue);
        }
    }
    
    void ACameraCharacter::MoveRight(float AxisValue)
    {
        if ((Controller != nullptr) && (AxisValue != 0.0f))
        {
            // Find out which way is right
            const FRotator Rotation = Controller->GetControlRotation();
            const FRotator YawRotation(0, Rotation.Yaw, 0);
    
            // Get right vector 
            const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
            // Add movement in that direction
            AddMovementInput(Direction, AxisValue);
        }
    }
  9. Next, navigate to the ACameraCharacter::SetupPlayerInputComponent method, and implement the following code.

    //Called to bind functionality to input
    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);
    
    }

The Character class inherits from the Pawn class. In this example, we use the Pawn's AddControllerPitchInput, and AddControllerYawInput class methods to handle our Turn and LookUp logic.

Level Setup

To demonstrate the functionality of the Spring Arm Component, you will need to place some geometrical obstructions into your level.

  1. In the Editor, navigate to Window > Place Actors to open the Place Actors panel.

  2. In the Place Actors panel, select the Geometry tab, and drag a Box Brush into your level.

    Click image to enlarge

  3. In the Details panel, you can adjust the bounds of your Box Brush by navigating to the Brush Settings category, and adjusting the X, Y, and Z values.

    Click image to enlarge

  4. Next, from the Toolbar press PIE(Play In Editor).

    Toolbar Play In Editor

End Result

Spring Arm demonstration

When using WASD to move the character, you will notice that the camera now lags slightly behind the character's movement. Also, when you navigate your character near a wall, the camera attempts to reposition itself and moves in closer. When the character is free from obstruction, the Spring Arm returns the camera to its default Target Arm Length that is specified in its default class properties.

Help shape the future of Unreal Engine documentation! Tell us how we're doing so we can serve you better.
Take our survey
Dismiss