Creating a Camera Shake in Unreal Engine 5 with C++

Let's go over how to shake the camera using C++ in Unreal Engine 5.

Unreal Engine 5 Quinn standing in the camera shake section of the gym slightly blurred image
Quinn shaking the camera

Game Engine

Unreal Engine 5.5.1

IDE

Rider 2024.3.2

Project Name

MyProject

To start we need to add EngineCameras to the project's build script's PublicDependencyModuleNames. Below is the snippet. Here is the link to project's build script.

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput", "UMG", "Niagara", "EngineCameras" });

Next, let's create our own camera shake class that inherits UCameraShakeBase. In this example I called it MyCameraShake, the only thing we need to add is the constructor, it does not come by default like AActors or other Unreal classes. Below is the header file.

MyCameraShake.h

#pragma once

#include "CoreMinimal.h"
#include "Camera/CameraShakeBase.h"
#include "MyCameraShake.generated.h"


UCLASS()
class MYPROJECT_API UMyCameraShake : public UCameraShakeBase
{
	GENERATED_BODY()

public:
	// Constructor, set up and set defaults for the camera shake
	UMyCameraShake();
};

Next, inside the .cpp file the constructor is slightly different than other Unreal classes because it requires the FObjectInitializer with UCameraShakeBase(FObjectInitializer::Get()) because it doesn't have. constructor by default.

Camera shakes can accept one of four different patterns, Composite, Perlin, Sequence, or Wave. Visit Epic's official camera shake documentation to learn more. In this example we'll use the Perlin pattern. We first need to include the Perlin class with #include "Shakes/PerlinNoiseCameraShakePattern.h". Then, we create the Perlin class and set it's variables. The setup is very repetitive, most of the variables we want to edit are FPerlinNoiseShaker structs and they each have an Amplitude and Frequency float value. I set all values to 10.0f to exaggerate the effect. Finally, I set the duration value. All the variables default to 1.0f is not set.

MyCameraShake.cpp

#include "MyCameraShake.h"
#include "Shakes/PerlinNoiseCameraShakePattern.h"

// Sets default values
UMyCameraShake::UMyCameraShake()
	: UCameraShakeBase(FObjectInitializer::Get())
{
	// only shake the camera if it's not already shaking
	bSingleInstance = true;
	
	UPerlinNoiseCameraShakePattern* MyPerlinPattern = CreateDefaultSubobject<UPerlinNoiseCameraShakePattern>(TEXT("MyPerlinPattern"));
	
	MyPerlinPattern->X.Amplitude = 10.f;
	MyPerlinPattern->X.Frequency = 10.f;
	MyPerlinPattern->Y.Amplitude = 10.f;
	MyPerlinPattern->Y.Frequency = 10.f;
	MyPerlinPattern->Z.Amplitude = 10.f;
	MyPerlinPattern->Z.Frequency = 10.f;

	MyPerlinPattern->Pitch.Amplitude = 10.f;
	MyPerlinPattern->Pitch.Frequency = 10.f;
	MyPerlinPattern->Yaw.Amplitude = 10.f;
	MyPerlinPattern->Yaw.Frequency = 10.f;
	MyPerlinPattern->Roll.Amplitude = 10.f;
	MyPerlinPattern->Roll.Frequency = 10.f;

	MyPerlinPattern->FOV.Amplitude = 10.f;
	MyPerlinPattern->FOV.Frequency = 10.f;

	MyPerlinPattern->Duration = 2.f;

	SetRootShakePattern(MyPerlinPattern);
}

To showcase the camera shake I created a fairly basic trigger box that shakes the players camera on overlap. We first get the player controller via APlayerController* PlayerController = UGameplayStatics::GetPlayerController(this, 0); and then create a subclass of our newly created camera shake class with TSubclassOf<UMyCameraShake> CameraShakeClass = UMyCameraShake::StaticClass();. Finally, we can shake the camera with PlayerController->ClientStartCameraShake(CameraShakeClass);. Below is the trigger's .cpp file.

MyCameraShakeTrigger.cpp

#include "MyCameraShakeTrigger.h"
#include "MyCameraShake.h"
#include "Components/BoxComponent.h"
#include "Kismet/GameplayStatics.h"


// Sets default values
AMyCameraShakeTrigger::AMyCameraShakeTrigger()
{
	MyRoot = CreateDefaultSubobject<USceneComponent>(TEXT("MyRoot"));
	MyRoot->bVisualizeComponent = true;
	RootComponent = MyRoot;

	MyBoxComponent = CreateDefaultSubobject<UBoxComponent>(TEXT("MyBoxComponent"));
	MyBoxComponent->SetHiddenInGame(false);
	MyBoxComponent->SetupAttachment(RootComponent);

	MyBoxComponent->OnComponentBeginOverlap.AddDynamic(this, &AMyCameraShakeTrigger::OnBeginOverlap);
}

void AMyCameraShakeTrigger::OnBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (OtherActor != nullptr && OtherActor != this)
	{
		// Get the player controller
		APlayerController* PlayerController = UGameplayStatics::GetPlayerController(this, 0);
		if (PlayerController)
		{
			// Specify the Camera Shake class
			TSubclassOf<UMyCameraShake> CameraShakeClass = UMyCameraShake::StaticClass();
			if (CameraShakeClass)
			{
				// Play the camera shake
				PlayerController->ClientStartCameraShake(CameraShakeClass);
			}
		}
	}
}

After compiling the code, the MyCameraShakeTrigger can dragged directly into the game. Below is the final effect in the gym.

Unreal Engine 5 Quinn running into the box collision that triggers the camera shake inside the gym
Quinn shaking the cam

Hopefully this helps, when programming this feature I got tripped up in a few places.

Loading...