How can I take a screenshot while in-game through C++?

Hello, so my issue is that I can’t save a screenshot through code. Now, my basic idea was to make it so that every second TakeScreenshot() function gets called, and then I take a screenshot that’s corresponding to my selected camera (I have multiple cameras and I want to take a screenshot from each one of them every second) and then I want to save them in screenshot folder.

My TakeScreenshot() function currently looks like this:

void ARealCar::TakeScreenshot()
{
    APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();

    if (!PlayerController)
    {
        UE_LOG(LogTemp, Warning, TEXT("PlayerController is null"));
        return;
    }

    // Store the original view target
    OriginalViewTarget = PlayerController->GetViewTarget();

    // Switch to each camera and capture a screenshot

    if (Camera1 && PlayerController)
    {
        PlayerController->SetViewTarget(Camera1->GetOwner());

        // Remove the callback to avoid multiple additions
        UGameViewportClient* GameViewportClient = GEngine->GameViewport;
        GameViewportClient->OnScreenshotCaptured().RemoveAll(this);

        // Capture the screenshot with a callback
        GameViewportClient->OnScreenshotCaptured().AddUObject(this, &ARealCar::OnScreenshotCaptured);

        // Trigger the screenshot capture
        UE_LOG(LogTemp, Warning, TEXT("Calling RequestScreenshot for %s"), *Camera1->GetName());
        FScreenshotRequest::RequestScreenshot(
            GetScreenshotPath(), 
            false, 
            false
        );
    }
    
    ScreenshotIndex++;
}

so, it does end up adding OnScreenshotCaptured() delegate and then, once I call RequestScreenshot() it does actually execute. And OnScreenshotCaptured() looks like this:

void ARealCar::OnScreenshotCaptured(int32 SizeX, int32 SizeY, const TArray<FColor>& Bitmap)
{
    UE_LOG(LogTemp, Warning, TEXT("Started OnScreenshotCaptured"));
    
    // Generate a filename based on the current date
    const FDateTime Now = FDateTime::Now();

    // store screenshot in Project directory next to main UProject/EXE based on the build type
    #if WITH_EDITOR
    const FString ImageDirectory = FString::Printf(TEXT("%s%s"), *FPaths::ProjectDir(), TEXT("Screenshots"));
    #else
    const FString ImageDirectory = FString::Printf(TEXT("%s/../%s"), *FPaths::ProjectDir(), TEXT("Screenshots"));
    #endif

    const FString ImageFilename = FString::Printf(TEXT("%s/Screenshot_%d%02d%02d_%02d%02d%02d_%03d.png"), *ImageDirectory, Now.GetYear(), Now.GetMonth(), Now.GetDay(), Now.GetHour(), Now.GetMinute(), Now.GetSecond(), Now.GetMillisecond());
    
    FScreenshotRequest::RequestScreenshot(ImageFilename, false, false);
    UE_LOG(LogTemp, Warning, TEXT("Saved screenshot at; %s"), *ImageFilename);

}

So here i’m getting the filename, and calling FScreenshotRequest::RequestScreenshot() to supposedly save the image. And when I run the game, each second the OnScreenCaptured() gets called, and my log looks something like this:

LogTemp: Warning: Calling RequestScreenshot for Camera1
LogTemp: Warning: Started OnScreenshotCaptured
LogTemp: Warning: Saved screenshot at; …/…/…/…/…/projects/Games/ZPD/Screenshots/Screenshot_20231126_120731_855.png

As for the screenshot saving logic, I took it from here, though I had to modify const FString ImageDirectory = FString::Printf(TEXT("%s%s"), *FPaths::ProjectDir() and remove the slash between %s/%s to prevent it from adding a double slash between/ZPD//Screenshots . I don’t know how outdated and deprecated that code is, but i couldn’t really find any other guide that does something like that. Also it’s important that I don’t slow down the game while taking the screenshots (like it happens with high-res screenshots), as well as that I don’t actually switch my view to the camera that I want to take a screenshot from (that’s why i’m using PlayerController->SetViewTarget(Camera1->GetOwner()); which seems to not change my view of the camera.

So yeah, any help would be appreciated. Thanks!

This was the best solution for me:

Taking In-Game Screenshots With UI in Shipping builds of UE Games - Rhyce.dev