All skills
quodsoler avatar

/ue-gameplay-cameras

@f3742d7

Use when building or fixing Unreal Engine cameras — spring-arm third-person rigs, first-person cameras, view-target blends, camera shakes, camera modifiers, cine cameras, or the Gameplay Camera System plugin. Also use when the user mentions 'APlayerCameraManager', 'USpringArmComponent', 'TargetArmLength', 'bUsePawnControlRotation', 'SetViewTargetWithBlend', 'UpdateViewTarget', 'CalcCamera', 'UCameraModifier', 'camera shake', 'UCameraShakeBase', 'FMinimalViewInfo', 'UGameplayCameraComponent', 'camera rig', 'camera director' or 'ShowDebug Camera'. For Sequencer shots, see ue-sequencer-cinematics; for the classes that own the camera, see ue-gameplay-framework; for input, see ue-input-system.

Use this Skill: https://skilld.dev/gh/quodsoler/unreal-engine-skills/ue-gameplay-cameras

This session only. Nothing lands on disk.

referencesclassic-camera-stack.md

≈5.4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Classic Camera Stack Reference (UE 5.8)

Everything here is in the Engine module (Source/Runtime/Engine/Classes/Camera, Classes/GameFramework), the CinematicCamera module, or the EngineCameras plugin. Build.cs: "Engine", plus "CinematicCamera" and "EngineCameras" as needed.

FMinimalViewInfo

Camera/CameraTypes.h. This is the struct every camera path produces.

Field Type Notes
Location FVector world position
Rotation FRotator world orientation
FOV float horizontal degrees, perspective only
DesiredFOV float transient; pre-aspect-adjustment value
FirstPersonFOV float applied to primitives tagged first person
FirstPersonScale float shrinks first-person primitives toward the camera
OrthoWidth float orthographic only
bAutoCalculateOrthoPlanes bool with AutoPlaneShift, bUpdateOrthoPlanes, bUseCameraHeightAsViewTarget
OrthoNearClipPlane / OrthoFarClipPlane float orthographic clip range
PerspectiveNearClipPlane float negative means use the global default
AspectRatio float width / height
AspectRatioAxisConstraint TOptional<EAspectRatioAxisConstraint> override for this view
bConstrainAspectRatio uint32:1 adds black bars when the viewport differs
bUseFirstPersonParameters uint32:1 gates FirstPersonFOV / FirstPersonScale
bUseFieldOfViewForLOD uint32:1 FOV feeds mesh LOD selection
ProjectionMode TEnumAsByte<ECameraProjectionMode::Type> perspective or orthographic
PostProcessBlendWeight float 0 disables PostProcessSettings
PostProcessSettings FPostProcessSettings see below
OffCenterProjectionOffset FVector2D proportion of screen dimensions
PreviousViewTransform TOptional<FTransform> motion-vector hint
OverscanResolutionFraction float resolution scale that follows overscan
CropFraction float 1.0 means no crop

APlayerCameraManager

Camera/PlayerCameraManager.h. UCLASS(notplaceable, transient, BlueprintType, Blueprintable, Config=Engine, MinimalAPI), base AActor.

Key state: PCOwner, CameraStyle (FName), DefaultFOV, DefaultOrthoWidth, DefaultAspectRatio, ViewTarget and PendingViewTarget (FTViewTarget), BlendTimeToGo, BlendParams (FViewTargetTransitionParams), ModifierList, DefaultModifiers, FreeCamDistance, ViewPitchMin, ViewPitchMax, ViewYawMin, ViewYawMax, ViewRollMin, ViewRollMax, FadeColor, FadeAmount, ColorScale, bIsOrthographic.

Virtuals worth overriding:

virtual void UpdateCamera(float DeltaTime);
virtual void DoUpdateCamera(float DeltaTime);
virtual void UpdateViewTarget(FTViewTarget& OutVT, float DeltaTime);
virtual void UpdateViewTargetInternal(FTViewTarget& OutVT, float DeltaTime);
virtual void ApplyCameraModifiers(float DeltaTime, FMinimalViewInfo& InOutPOV);
virtual void InitializeFor(class APlayerController* PC);
virtual void ProcessViewRotation(float DeltaTime, FRotator& OutViewRotation, FRotator& OutDeltaRot);
virtual void SetViewTarget(class AActor* NewViewTarget, FViewTargetTransitionParams TransitionParams = FViewTargetTransitionParams());
virtual void AssignViewTarget(AActor* NewTarget, FTViewTarget& VT, struct FViewTargetTransitionParams TransitionParams = FViewTargetTransitionParams());
virtual FRotator GetCameraRotation() const;
virtual FVector GetCameraLocation() const;
virtual void LimitViewPitch(FRotator& ViewRotation, float InViewPitchMin, float InViewPitchMax);
virtual void LimitViewYaw(FRotator& ViewRotation, float InViewYawMin, float InViewYawMax);
virtual void LimitViewRoll(FRotator& ViewRotation, float InViewRollMin, float InViewRollMax);
virtual void DisplayDebug(class UCanvas* Canvas, const FDebugDisplayInfo& DebugDisplay, float& YL, float& YPos) override;

Read-only accessors: AActor* GetViewTarget() const, virtual const FMinimalViewInfo& GetCameraCacheView() const, virtual const FMinimalViewInfo& GetLastFrameCameraCacheView() const, float GetCameraCacheTime() const, float GetLockedFOV() const. OnBlendComplete() returns the FOnBlendComplete event fired when PendingViewTarget is promoted.

BlueprintUpdateCamera(AActor* CameraTarget, FVector& NewCameraLocation, FRotator& NewCameraRotation, float& NewCameraFOV) is the Blueprint hook that short-circuits UpdateViewTarget when it returns true.

FTViewTarget and FViewTargetTransitionParams

USTRUCT(BlueprintType)
struct FTViewTarget
{
    TObjectPtr<class AActor> Target;
    struct FMinimalViewInfo POV;
    class APlayerState* GetPlayerState() const;
    void SetNewTarget(AActor* NewTarget);
    class APawn* GetTargetPawn() const;
    bool Equal(const FTViewTarget& OtherTarget) const;
    void CheckViewTarget(APlayerController* OwningController);
};

FViewTargetTransitionParams holds BlendTime, BlendFunction (TEnumAsByte<enum EViewTargetBlendFunction>), BlendExp, bLockOutgoing, and float GetBlendAlpha(const float& TimePct) const.

EViewTargetBlendOrder (VTBlendOrder_Base, VTBlendOrder_Override) exists alongside EViewTargetBlendFunction for systems that stack blends.

UCameraComponent

Camera/CameraComponent.h, base USceneComponent, ClassGroup=Camera, meta=(BlueprintSpawnableComponent).

Properties: FieldOfView, FirstPersonFieldOfView, FirstPersonScale, OrthoWidth, bAutoCalculateOrthoPlanes, AutoPlaneShift, OrthoNearClipPlane, OrthoFarClipPlane, AspectRatio, bConstrainAspectRatio, bUseFieldOfViewForLOD, Overscan, bScaleResolutionWithOverscan, bCropOverscan, ProjectionMode, bLockToHmd, bUsePawnControlRotation, bEnableFirstPersonFieldOfView, bEnableFirstPersonScale, PostProcessBlendWeight, PostProcessSettings.

Setters exist for nearly all of them (SetFieldOfView, SetOrthoWidth, SetAspectRatio, SetProjectionMode, SetPostProcessBlendWeight, …). The one virtual you normally override is:

virtual void GetCameraView(float DeltaTime, FMinimalViewInfo& DesiredView);

Also useful: void AddOrUpdateBlendable(TScriptInterface<IBlendableInterface> InBlendableObject, float InWeight = 1.0f), void RemoveBlendable(TScriptInterface<IBlendableInterface> InBlendableObject), void AddAdditiveOffset(FTransform const& Transform, float FOV) / ClearAdditiveOffset() / GetAdditiveOffset(FTransform& OutAdditiveOffset, float& OutAdditiveFOVOffset) const, void AddExtraPostProcessBlend(FPostProcessSettings const& PPSettings, float PPBlendWeight) / ClearExtraPostProcessBlends() (stored only — not applied by GetCameraView, and only the level-editor viewport reads them, Camera/CameraComponent.h:323), and virtual void NotifyCameraCut().

ACameraActor wraps one: TEnumAsByte<EAutoReceiveInput::Type> AutoActivateForPlayer, int32 GetAutoActivatePlayerIndex() const, class UCameraComponent* GetCameraComponent() const.

Post-process on a camera

UCameraComponent::PostProcessSettings is an FPostProcessSettings (Engine/Scene.h) blended at PostProcessBlendWeight (0 = off, 1 = full). Every field is gated by a matching bOverride_ flag — setting DepthOfFieldFstop without bOverride_DepthOfFieldFstop = true does nothing:

// MyCharacter.cpp - include Camera/CameraComponent.h
void AMyCharacter::ApplyCinematicLook(UCameraComponent* Camera)
{
    Camera->PostProcessBlendWeight = 1.f;
    Camera->PostProcessSettings.bOverride_MotionBlurAmount = true;
    Camera->PostProcessSettings.MotionBlurAmount = 0.2f;
    Camera->PostProcessSettings.bOverride_DepthOfFieldFstop = true;
    Camera->PostProcessSettings.DepthOfFieldFstop = 2.8f;
}

Camera post-process is blended after all volumes (LocalPlayer.cpp:970), so it overrides any APostProcessVolume regardless of volume priority. FWeightedBlendables inside the settings holds material blendables added by AddOrUpdateBlendable.

UCameraModifier

Camera/CameraModifier.h, UCLASS(BlueprintType, Blueprintable, MinimalAPI), base UObject.

virtual bool ModifyCamera(float DeltaTime, struct FMinimalViewInfo& InOutPOV);
virtual bool ProcessViewRotation(class AActor* ViewTarget, float DeltaTime, FRotator& OutViewRotation, FRotator& OutDeltaRot);
virtual void AddedToCamera(APlayerCameraManager* Camera);
virtual void UpdateAlpha(float DeltaTime);
virtual float GetTargetAlpha();
virtual void EnableModifier();
virtual void DisableModifier(bool bImmediate = false);
virtual void ToggleModifier();
virtual bool IsDisabled() const;
virtual bool IsPendingDisable() const;
virtual AActor* GetViewTarget() const;
virtual void DisplayDebug(class UCanvas* Canvas, const FDebugDisplayInfo& DebugDisplay, float& YL, float& YPos);

State: Priority (uint8, 0 = highest), bExclusive, bDebug, CameraOwner, AlphaInTime, AlphaOutTime, Alpha. Blueprint-only hooks: BlueprintModifyCamera and BlueprintModifyPostProcess.

There is a second, non-virtual-extension overload virtual void ModifyCamera(float DeltaTime, FVector ViewLocation, FRotator ViewRotation, float FOV, FVector& NewViewLocation, FRotator& NewViewRotation, float& NewFOV) used internally to bridge to Blueprint. Override the FMinimalViewInfo form.

Camera shakes

UCameraShakeBase (Camera/CameraShakeBase.h, UCLASS(Abstract, Blueprintable, EditInlineNew, MinimalAPI)) owns a private RootShakePattern and exposes UCameraShakePattern* GetRootShakePattern() const, void SetRootShakePattern(UCameraShakePattern* InPattern) and the template helper ChangeRootShakePattern<ShakePatternType>(). Runtime state: bSingleInstance, ShakeScale, APlayerCameraManager* GetCameraManager() const, ECameraShakePlaySpace GetPlaySpace() const, const FMatrix& GetUserPlaySpaceMatrix() const.

Lifecycle calls the manager makes: StartShake(APlayerCameraManager* Camera, float Scale, ECameraShakePlaySpace InPlaySpace, FRotator UserPlaySpaceRot = FRotator::ZeroRotator) or StartShake(const FCameraShakeBaseStartParams& Params), then UpdateAndApplyCameraShake(float DeltaTime, float Alpha, FMinimalViewInfo& InOutPOV), bool IsFinished() const, StopShake(bool bImmediately = true), TeardownShake().

Writing a shake pattern

// MyShakePattern.h
#pragma once

#include "CoreMinimal.h"
#include "Shakes/SimpleCameraShakePattern.h"
#include "MyShakePattern.generated.h"

UCLASS()
class MYGAME_API UMyShakePattern : public USimpleCameraShakePattern
{
    GENERATED_BODY()

public:
    UMyShakePattern(const FObjectInitializer& ObjInit);

    UPROPERTY(EditAnywhere, Category = "Shake")
    float PitchAmplitude = 2.f;

    UPROPERTY(EditAnywhere, Category = "Shake")
    float PitchFrequency = 10.f;

protected:
    virtual void UpdateShakePatternImpl(const FCameraShakePatternUpdateParams& Params, FCameraShakePatternUpdateResult& OutResult) override;
};

// MyShakePattern.cpp
#include "MyShakePattern.h"

UMyShakePattern::UMyShakePattern(const FObjectInitializer& ObjInit)
    : Super(ObjInit)
{
    Duration = 0.4f;
    BlendInTime = 0.05f;
    BlendOutTime = 0.2f;
}

void UMyShakePattern::UpdateShakePatternImpl(const FCameraShakePatternUpdateParams& Params, FCameraShakePatternUpdateResult& OutResult)
{
    // Advance the inherited State: it tracks Duration and the blend in/out, and IsFinishedImpl reads it.
    const float BlendWeight = State.Update(Params.DeltaTime);
    OutResult.Rotation.Pitch = PitchAmplitude * FMath::Sin(State.GetElapsedTime() * PitchFrequency * 2.f * UE_PI);
    OutResult.ApplyScale(BlendWeight);
}

USimpleCameraShakePattern (module "EngineCameras") supplies Duration, BlendInTime, BlendOutTime and implements the info/start/finish/stop/teardown hooks, so a subclass usually only writes UpdateShakePatternImpl. That override must call State.Update(Params.DeltaTime) and scale its output by the returned weight, as the shipped patterns do (PerlinNoiseCameraShakePattern.cpp:49-50); IsFinishedImpl returns !State.IsPlaying(), so a pattern that never updates State never finishes. The full protected set on UCameraShakePattern:

virtual void GetShakePatternInfoImpl(FCameraShakeInfo& OutInfo) const;
virtual void StartShakePatternImpl(const FCameraShakePatternStartParams& Params);
virtual void UpdateShakePatternImpl(const FCameraShakePatternUpdateParams& Params, FCameraShakePatternUpdateResult& OutResult);
virtual void ScrubShakePatternImpl(const FCameraShakePatternScrubParams& Params, FCameraShakePatternUpdateResult& OutResult);
virtual bool IsFinishedImpl() const;
virtual void StopShakePatternImpl(const FCameraShakePatternStopParams& Params);
virtual void TeardownShakePatternImpl();

Shipped patterns

Class Module Shape
UPerlinNoiseCameraShakePattern EngineCameras FPerlinNoiseShaker (Amplitude, Frequency) on X/Y/Z, Pitch/Yaw/Roll, FOV, plus LocationAmplitudeMultiplier, LocationFrequencyMultiplier, RotationAmplitudeMultiplier, RotationFrequencyMultiplier
UWaveOscillatorCameraShakePattern EngineCameras FWaveOscillator per axis; same multiplier layout
UCompositeCameraShakePattern EngineCameras ChildPatterns, runs several patterns as one
ULegacyCameraShakePattern EngineCameras backs ULegacyCameraShake's oscillator fields
USequenceCameraShakePattern TemplateSequence plays a UCameraAnimationSequence

ULegacyCameraShake (UCLASS(MinimalAPI, Blueprintable, HideCategories = (CameraShakePattern))) keeps the oscillator-style authoring surface (FFOscillator, FROscillator, FVOscillator, OscillationDuration, OscillationBlendInTime, OscillationBlendOutTime) and offers the statics static ULegacyCameraShake* StartLegacyCameraShake(APlayerCameraManager* PlayerCameraManager, TSubclassOf<ULegacyCameraShake> ShakeClass, float Scale = 1.f, ECameraShakePlaySpace PlaySpace = ECameraShakePlaySpace::CameraLocal, FRotator UserPlaySpaceRot = FRotator::ZeroRotator) and static ULegacyCameraShake* StartLegacyCameraShakeFromSource(APlayerCameraManager* PlayerCameraManager, TSubclassOf<ULegacyCameraShake> ShakeClass, UCameraShakeSourceComponent* SourceComponent, float Scale = 1.f, ECameraShakePlaySpace PlaySpace = ECameraShakePlaySpace::CameraLocal, FRotator UserPlaySpaceRot = FRotator::ZeroRotator). UDefaultCameraShakeBase is a UCameraShakeBase whose RootShakePattern subobject class is UPerlinNoiseCameraShakePattern.

UCameraModifier_CameraShake

The manager creates one by default; it owns the running shakes.

virtual UCameraShakeBase* AddCameraShake(TSubclassOf<UCameraShakeBase> NewShake, const FAddCameraShakeParams& Params);
virtual void GetActiveCameraShakes(TArray<FActiveCameraShakeInfo>& ActiveCameraShakes) const;
virtual void RemoveCameraShake(UCameraShakeBase* ShakeInst, bool bImmediately = true);
virtual void RemoveAllCameraShakesOfClass(TSubclassOf<UCameraShakeBase> ShakeClass, bool bImmediately = true);
virtual void RemoveAllCameraShakesFromSource(const UCameraShakeSourceComponent* SourceComponent, bool bImmediately = true);
virtual void RemoveAllCameraShakesOfClassFromSource(TSubclassOf<UCameraShakeBase> ShakeClass, const UCameraShakeSourceComponent* SourceComponent, bool bImmediately = true);
virtual void RemoveAllCameraShakes(bool bImmediately = true);

FAddCameraShakeParams carries Scale, PlaySpace, UserPlaySpaceRot, SourceComponent, Initializer (FOnInitializeCameraShake) and DurationOverride (TOptional<float>). Supplying an Initializer opts the shake out of pooling.

UCameraShakeSourceComponent

Attenuation (ECameraShakeAttenuation), InnerAttenuationRadius, OuterAttenuationRadius, CameraShake, bAutoStart. Methods: void Start(), void StartCameraShake(TSubclassOf<UCameraShakeBase> InCameraShake, float Scale=1.f, ECameraShakePlaySpace PlaySpace = ECameraShakePlaySpace::CameraLocal, FRotator UserPlaySpaceRot = FRotator::ZeroRotator), void StopAllCameraShakesOfType(TSubclassOf<UCameraShakeBase> InCameraShake, bool bImmediately = true), void StopAllCameraShakes(bool bImmediately = true), float GetAttenuationFactor(const FVector& Location) const. ACameraShakeSourceActor is the placeable actor form.

Camera animation sequences

UEngineCamerasSubsystem (a UWorldSubsystem in the EngineCameras plugin) plays UCameraAnimationSequence assets on a player:

static UEngineCamerasSubsystem* GetEngineCamerasSubsystem(const UWorld* InWorld);
FCameraAnimationHandle PlayCameraAnimation(APlayerController* PlayerController, UCameraAnimationSequence* Sequence, FCameraAnimationParams Params);
bool IsCameraAnimationActive(APlayerController* PlayerController, const FCameraAnimationHandle& Handle) const;
void StopCameraAnimation(APlayerController* PlayerController, const FCameraAnimationHandle& Handle, bool bImmediate = false);
void StopAllCameraAnimationsOf(APlayerController* PlayerController, UCameraAnimationSequence* Sequence, bool bImmediate = false);
void StopAllCameraAnimations(APlayerController* PlayerController, bool bImmediate = false);

UCameraAnimationCameraModifier is the modifier that applies them.

USpringArmComponent

GameFramework/SpringArmComponent.h, base USceneComponent.

Property Effect
TargetArmLength boom length before collision
SocketOffset offset in the boom's rotated space — moves with the camera
TargetOffset offset in world space — stays vertical
bDoCollisionTest sweep from the pivot to the camera
ProbeChannel (TEnumAsByte<ECollisionChannel>) channel for that sweep, normally ECC_Camera
ProbeSize sphere radius of the sweep
bUsePawnControlRotation drive rotation from APawn::GetViewRotation()
bInheritPitch / bInheritYaw / bInheritRoll which parent rotation axes pass through
bEnableCameraLag / CameraLagSpeed / CameraLagMaxDistance positional smoothing
bEnableCameraRotationLag / CameraRotationLagSpeed rotational smoothing
bUseCameraLagSubstepping / CameraLagMaxTimeStep frame-rate-independent damping
bDrawDebugLagMarkers draws the lag target

Accessors and virtuals: FRotator GetTargetRotation() const, bool IsCollisionFixApplied() const, static const FName SocketName, virtual FRotator GetDesiredRotation() const, virtual void UpdateDesiredArmLocation(bool bDoTrace, bool bDoLocationLag, bool bDoRotationLag, float DeltaTime), virtual FVector BlendLocations(const FVector& DesiredArmLocation, const FVector& TraceHitLocation, bool bHitSomething, float DeltaTime).

Actor and pawn hooks

// AActor
virtual void CalcCamera(float DeltaTime, struct FMinimalViewInfo& OutResult);
virtual bool HasActiveCameraComponent(bool bForceFindCamera = false) const;
virtual bool HasActivePawnControlCameraComponent() const;
virtual void GetActorEyesViewPoint(FVector& OutLocation, FRotator& OutRotation) const;
uint8 bFindCameraComponentWhenViewTarget:1;

// APawn
virtual FRotator GetViewRotation() const;
virtual FVector GetPawnViewLocation() const;
virtual void RecalculateBaseEyeHeight();
float BaseEyeHeight;

// APlayerController
virtual void GetPlayerViewPoint(FVector& out_Location, FRotator& out_Rotation) const override;
virtual void CalcCamera(float DeltaTime, struct FMinimalViewInfo& OutResult) override;
virtual void SpawnPlayerCameraManager();
virtual void AutoManageActiveCameraTarget(AActor* SuggestedTarget);

APawn does not declare CalcCamera — the inherited AActor version runs, which is why bFindCameraComponentWhenViewTarget (default true on every actor, Actor.cpp:320) usually routes to the camera component instead. A subclass override of CalcCamera always runs for a non-ACameraActor view target; only calling Super brings the component lookup back.

Cinematic cameras

UCineCameraComponent (module "CinematicCamera", base UCameraComponent, hides SetFieldOfView/SetAspectRatio):

Member Type
Filmback FCameraFilmbackSettings (setter SetFilmback)
LensSettings FCameraLensSettings (setter SetLensSettings)
FocusSettings FCameraFocusSettings (setter SetFocusSettings)
CropSettings FPlateCropSettings (setter SetCropSettings)
CurrentFocalLength float (setter SetCurrentFocalLength)
CurrentAperture float (setter SetCurrentAperture)
CurrentFocusDistance float, read-only
CurrentHorizontalFOV float, read-only
CustomNearClippingPlane float with bOverride_CustomNearClippingPlane

Helpers: float GetHorizontalFieldOfView() const, float GetVerticalFieldOfView() const, FString GetFilmbackPresetName() const, void SetFilmbackPresetByName(const FString& InPresetName), FString GetLensPresetName() const, void SetLensPresetByName(const FString& InPresetName).

ACineCameraActor adds FCameraLookatTrackingSettings LookatTrackingSettings, FVector GetLookatLocation() const, bool ShouldTickForTracking() const and overrides NotifyCameraCut().

Rigs:

Actor Animatable members
ACameraRig_Rail CurrentPositionOnRail (0–1), bLockOrientationToRail; spline component via GetRailSplineComponent
ACameraRig_Crane CranePitch, CraneYaw, CraneArmLength, bLockMountPitch, bLockMountYaw

Both override GetDefaultAttachComponent() so attaching a camera actor lands on the mount.

Source: SKILL.md on GitHub

No alerts3d3 checks · Risk SAFE
  • Gen Agent Trust Hub3d

    The skill provides comprehensive documentation for Unreal Engine camera systems. It is generally safe for developer use, though it includes a surface for indirect prompt injection by instructing the agent to read local project context files that could be manipulated by an external actor.

  • Socket3d

    No alerts

  • Snyk3d

    Risk: LOW · No issues

Signed by skilld at f3742d7. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 3 days ago
metadata
{
  "version": "2.0.0",
  "engine": "5.8"
}

README badge

README badge for quodsoler/unreal-engine-skills/ue-gameplay-cameras