Camera Transition Not Working in Unreal Engine 5

Hi there,

I’m working on a project in Unreal Engine 5 and have implemented camera transition functionality. Although the camera transition appears to be successful in the logs, it does not actually occur in the game. Here is the code and setup I am using:

#include "CameraManager.h"
#include "Camera/CameraActor.h"
#include "Kismet/GameplayStatics.h"

// Sets default values
ACameraManager::ACameraManager()
{
    PrimaryActorTick.bCanEverTick = true;
}

void ACameraManager::SwitchToNextCamera()
{
    if (Cameras.Num() > 0)
    {
        CurrentCameraIndex = (CurrentCameraIndex + 1) % Cameras.Num();
        SwitchToCamera(CurrentCameraIndex);
    }
}

void ACameraManager::SwitchToCamera(int32 CameraIndex)
{
    if (Cameras.IsValidIndex(CameraIndex))
    {
        ACameraActor* NewCamera = Cast<ACameraActor>(Cameras[CameraIndex]);
        if (NewCamera)
        {
            APlayerController* PlayerController = UGameplayStatics::GetPlayerController(this, 0);

            // Check logs
            UE_LOG(LogTemp, Warning, TEXT("Switching to camera index: %d"), CameraIndex);
            UE_LOG(LogTemp, Warning, TEXT("Current Camera: %s"), *PlayerController->GetViewTarget()->GetName());
            UE_LOG(LogTemp, Warning, TEXT("New Camera: %s"), *NewCamera->GetName());

            // Switch camera instantly without blend
            PlayerController->SetViewTarget(NewCamera);

            UE_LOG(LogTemp, Warning, TEXT("Successfully switched to camera: %s"), *NewCamera->GetName());
        }
        else
        {
            UE_LOG(LogTemp, Error, TEXT("Failed to cast to ACameraActor for index: %d"), CameraIndex);
        }
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("Invalid CameraIndex: %d"), CameraIndex);
    }
}

void ACameraManager::BeginPlay()
{
    Super::BeginPlay();

    // Find all ACameraActor and add to Cameras array
    UGameplayStatics::GetAllActorsOfClass(GetWorld(), ACameraActor::StaticClass(), Cameras);

    if (Cameras.Num() > 0)
    {
        CurrentCameraIndex = 0;
        UE_LOG(LogTemp, Warning, TEXT("Found %d cameras"), Cameras.Num());
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("No cameras found"));
    }
}

void ACameraManager::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
}

Problem Description:

  • The camera transition appears to be successful in the logs, and log messages in the SwitchToCamera function are correctly output.
  • However, in the actual game, the camera does not switch.
  • I have confirmed that the PlayerController is correctly returned and also tested switching cameras directly using SetViewTarget.

What I’ve Tried:

  • Verified the camera actor’s position and rotation.
  • Checked the validity and state of the player controller.
  • Tested camera transitions using alternative methods.
  • Verified camera view in the editor and checked debug logs.

What additional steps or checks should I perform to resolve this issue? Any help would be greatly appreciated!

Thank you.

There are a few ways to do this. What we do is make “controllable camera character” with a small collision sphere and flying. Then just Possess() the controllable camera character with your player controller. That way you can possess, move, turn, etc. the controlled camera just like any other character.

I am assuming your ACameraManager inherits from Epic’s APlayerCameraManager?

In that case, your constructor doesn’t call the parent constructor which means you’re missing a bunch of settings and components.
You should go with:

ACameraManager::ACameraManager(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
    PrimaryActorTick.bCanEverTick = true;
}

Running further with my assumption, I’m a bit confused about PlayerController->SetViewTarget(NewCamera); as this will just call back ACameraManager::SetViewTarget() which is not inherently wrong but… just curious.

Or maybe my assumption was wrong?

If that is the case you might check your actual APlayerCameraManager and see if it is valid. (because APlayerController::SetViewTarget() will fail silently if there is no valid camera manager)

No… unfortunately i made my CameraManager from just Actor . Well as for the PlayerController->SetViewTarget(NewCamera); SetViewTarget() function would probably be an PlayerController’s Function in this case… because SetViewTarget() is not particularly defined at CameraManager class. but could this be problem?

According to few of my Logs, CameraManager seems to be online

LogTemp: Warning: CameraManager found
LogWorldPartition: New Streaming Source: CameraPlayerController_0 -> Position: X=1040.008 Y=1211.294 Z=90.000
LogTemp: Warning: Found 2 cameras
PIE: Server logged in
PIE: Play in editor total start time 0.167 seconds.
LogTemp: Warning: Switching to camera index: 1
LogTemp: Warning: Current Camera: BP_FirstPersonCharacter_C_0
LogTemp: Warning: New Camera: BP_Cam1_C_UAID_D843AE24536D4B1C02_1293429303
LogTemp: Warning: Successfully switched to camera: BP_Cam1_C_UAID_D843AE24536D4B1C02_1293429303
LogTemp: Warning: Switched Camera

One thing not mentioned is that I am currently using the method to Scene Capture Component 2D (under each Camera Actors) and setting the Texture Target To RT_CameraFeed (Render Target). And I made an HUD and imported RT_CameraFeed as an image brush.

Could this method be related to my problem on camera changing?

Not really… Well, there is SetViewTarget() in the PlayerController but the whole implementation is this:

void APlayerController::SetViewTarget(class AActor* NewViewTarget, struct FViewTargetTransitionParams TransitionParams)
{
	if (PlayerCameraManager)
	{
		PlayerCameraManager->SetViewTarget(NewViewTarget, TransitionParams);
	}
}

This is why I asked if your APlayerCameraManager is set. Then again, if you are not deriving from it the default player camera manager should be provided for you and working. (check it anyway just in case)

I doubt that unless you are checking if the camera change works through the UI and the render target. Still, try to isolate the problem by disabling the the part that looks suspicious to you. You know your code best so you should follow your intuition.