Skip to content

Creating Camera Curves

This tutorial walks you through creating custom camera effects using Motion's curve system. You'll learn to create head bob, landing impact, and other procedural camera animations.

Overview

Motion's camera system uses UCurveVector assets to define procedural animations. Each curve has X, Y, Z channels that can represent either location or rotation offsets applied to the camera over time.

Prerequisites

  • MotionCameraComponent added to your character
  • MotionCameraEventBus component for receiving events
  • Basic familiarity with Unreal's Curve Editor

Step 1: Create a Curve Asset

  1. In Content Browser, right-click and select Miscellaneous > Curve
  2. Choose CurveVector as the curve type
  3. Name it descriptively (e.g., Curve_HeadBob or Curve_LandingImpact)

Step 2: Design Your Curve

Open the curve asset in the Curve Editor. You have three channels:

ChannelLocationRotation
X (Red)Right/LeftRoll (tilt)
Y (Green)Forward/BackPitch (nod)
Z (Blue)Up/DownYaw (turn)

TIP

Each curve channel affects both location and rotation simultaneously. For location-only effects, keep values small (0.1-1.0). For rotation-only effects, design curves that return to zero position to minimize visual location offset.

Example: Head Bob Curve

A subtle walking head bob:

Time    X        Y        Z
0.0     0        0        0
0.25    0.5      0        1.0
0.5     0        0        0
0.75   -0.5      0        1.0
1.0     0        0        0

This creates a figure-8 motion: slight horizontal sway with vertical bounce.

Example: Landing Impact Curve

A sharp downward impact that recovers:

Time    X        Y        Z
0.0     0        0        0
0.05    0        0       -5.0    (sharp drop)
0.15    0        0       -3.0    (partial recovery)
0.4     0        0        0      (full recovery)

Curve Editor Tips

  • Right-click on timeline to add keyframes
  • Shift+click to add keyframe at current time
  • Use Auto tangents for smooth interpolation
  • Use Linear tangents for sharp, mechanical motion
  • Ctrl+drag to scale sections

Step 3: Configure the Motion Curve Structure

In your component or Blueprint, create an FMotionCurve:

Blueprint Configuration

  1. Create a variable of type Struct Motion Curve
  2. Configure these properties:
PropertyDescriptionExample Value
IdentifierUnique FName identifier for this curve"WalkHeadBob"
CurveAssetReference to your UCurveVectorCurve_HeadBob
bShouldLoopRepeat when reaching endtrue for head bob
bShouldReversePlay backwards after forwardtrue for smooth loops
TickratePlayback speed multiplier1.0 (normal speed)
MultiplierScale the effect intensity0.5 (subtle), 2.0 (intense)
FalloutSmoothnessBlend out duration when removed0.0 default; use 0.2 for quick fade
bPauseAtNextZeroPause curve at next zero crossingtrue (safer transitions)
ZeroToleranceThreshold for zero detection0.01
bRemoveOnCompleteAuto-remove when curve completesfalse (manually remove)

C++ Configuration

cpp
FMotionCurve HeadBobCurve;
HeadBobCurve.Identifier = TEXT("WalkHeadBob");
HeadBobCurve.CurveAsset = LoadObject<UCurveVector>(nullptr, TEXT("/Game/Curves/CV_HeadBob"));
HeadBobCurve.bShouldLoop = true;
HeadBobCurve.bShouldReverse = true;
HeadBobCurve.Tickrate = 1.0f;
HeadBobCurve.Multiplier = 1.0f;
HeadBobCurve.FalloutSmoothness = 0.2f;

Step 4: Apply the Curve

Method 1: Direct Camera Component Access

cpp
// Add the curve
int32 Index = CameraComponent->AddMotionCurve(HeadBobCurve);

// Remove when done
CameraComponent->RemoveMotionCurve(TEXT("WalkHeadBob"));

Motion components use the Event Bus to broadcast camera effects:

cpp
// From any Motion component
BroadcastCameraEffect(HeadBobCurve, EMotionCameraAction::Add);

// To remove
BroadcastCameraEffect(HeadBobCurve, EMotionCameraAction::Remove);

Method 3: Blueprint Event Bus

  1. Get reference to MotionCameraEventBus component
  2. Call Broadcast Curve Event with your curve and action (Add/Remove/Pause/Resume)

Step 5: Test and Iterate

  1. Play in Editor
  2. Enable debug with bShowDebugInformation = true on the camera component
  3. Watch the curve effect in action
  4. Adjust curve keyframes and multiplier as needed

Debug Commands

bash
# See camera state
log LogMotionCamera Verbose

# View active curves
# Check camera component's GetActiveMotionCurves()

Common Curve Patterns

Walking Head Bob

  • Loop: Yes
  • Reverse: Yes
  • Tickrate: Match walking animation cycle
  • Multiplier: 0.3-0.5 (subtle)

Sprint Camera Shake

  • Loop: Yes
  • Reverse: Yes
  • Tickrate: Faster than walk (1.5-2.0)
  • Multiplier: 0.5-1.0 (more intense)

Landing Impact

  • Loop: No
  • Reverse: No
  • Tickrate: 1.0
  • Multiplier: Scale with fall distance

Jump Takeoff

  • Loop: No
  • Reverse: No
  • Tickrate: 1.0
  • Multiplier: 0.5-1.0

Weapon Recoil

  • Loop: No
  • Reverse: No
  • Tickrate: Fast (2.0-3.0)
  • Multiplier: Scale with weapon type

Curve Combinations

Multiple curves can be active simultaneously. Motion combines them additively:

cpp
// Add walking head bob
CameraComponent->AddMotionCurve(WalkHeadBob);

// Add breathing effect on top
CameraComponent->AddMotionCurve(BreathingCurve);

// Both effects combine

Pause and Resume

Control curves dynamically:

cpp
// Pause during cutscene
CameraComponent->SetMotionCurvePaused(TEXT("WalkHeadBob"), true);

// Resume after
CameraComponent->SetMotionCurvePaused(TEXT("WalkHeadBob"), false);

// Reset to start
CameraComponent->ResetMotionCurve(TEXT("WalkHeadBob"));

Static Offsets

For permanent camera adjustments (not time-based):

cpp
// Add a lean offset
CameraComponent->AddStaticLocationOffset(TEXT("Lean"), FVector(0, 10, 0));
CameraComponent->AddStaticRotationOffset(TEXT("Lean"), FRotator(0, 0, 5));

// Remove when done
CameraComponent->RemoveStaticLocationOffset(TEXT("Lean"));
CameraComponent->RemoveStaticRotationOffset(TEXT("Lean"));

Troubleshooting

IssueSolution
Curve not playingCheck AreCameraEffectsEnabled() - may be disabled by tag
Effect too subtleIncrease Multiplier value
Jerky animationUse Auto or User tangents in curve editor
Curve not loopingSet bShouldLoop = true
Effect persists after removalIncrease FalloutSmoothness for smoother fade
Multiple curves conflictingUse unique Identifier for each curve

See Also

Motion - Advanced First Person Character Controller