Hey guys I’ve been trying to crack this nut for a while and appreciate any advice/feedback you guys can give. I’ve got a VR game where I use the unreal spectator screen and all I want to do is add a UMG widget to it. I’ve seen some posts out there of people that in theory have ways to make it work, but I haven’t found anyone who’s actually written a step by step. All the advice I’ve seen seems to point to go something like this.
- Create a custom render target to write to.
- Use a scene capture 2d component to capture the gameplay and write it to the render target
- Incorporate the custom render target in a UI material
- Make a custom UMG widget that uses the UI material from step 3 as the background.
- Using c++ render the widget from step 4 to a second render target and use that as the texture input for the spectator screen
So I’ve implemented these steps but I’ve got a a problem. after just a few seconds of running my ram usage jumps exponentially till it hits 100%. My c++ is real weak so I’m not sure what I’m doing wrong. Here is the class responsible for rendering the widget to a render target.
SpectatorCamera.H
#pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "UMG.h" #include "SlateBasics.h" #include "SlateCore.h" #include "SWidget.h" #include "WidgetRenderer.h" #include "SpectatorCamera.generated.h" UCLASS(Blueprintable) class UFO_RODEO_API ASpectatorCamera : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties ASpectatorCamera(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: // Called every frame virtual void Tick(float DeltaTime) override; UFUNCTION(Category = "SpectatorCamera", BlueprintCallable) void RenderWidgetToTargetEnhanced(bool UseGamma, TextureFilter Filter, UUserWidget * WidgetToRender, FVector2D DrawSize, float DeltaTime, UPARAM(ref) UTextureRenderTarget2D * Target); FWidgetRenderer * renderer; };
SpectatorCamera.cpp
#include "SpectatorCamera.h" // Sets default values ASpectatorCamera::ASpectatorCamera() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; renderer = new FWidgetRenderer(false); } // Called when the game starts or when spawned void ASpectatorCamera::BeginPlay() { Super::BeginPlay(); } // Called every frame void ASpectatorCamera::Tick(float DeltaTime) { Super::Tick(DeltaTime); } void ASpectatorCamera::RenderWidgetToTargetEnhanced(bool UseGamma, TextureFilter Filter, UUserWidget * WidgetToRender, FVector2D DrawSize, float DeltaTime, UPARAM(ref) UTextureRenderTarget2D * Target) { if (!WidgetToRender) return; if (DrawSize == FVector2D(0, 0)) return; if (!Target) return; TSharedRef<SWidget> ref = WidgetToRender->TakeWidget(); renderer->DrawWidget(Target, ref, DrawSize, DeltaTime); }
I’m calling RenderWidgetToTargetEnhanced once a tick from a blueprint that inherits from this class.
I’ve also noticed that if in step 4, I just create a widget with no references to the first render target I don’t get the massive memory leak. I also don’t get my spectator camera in that case though so it doesn’t really help, but it does make me wonder if the problem is really my c++ code or something else.
Anyone out there either have a solution to my memory leak problem or a better alternative on how to add widgets to a spectator screen?