Hello,
We’ve found that the app continues rendering even when the window is minimized.
I noticed there’s some code that appears to handle rendering suspension:
https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Source/Runtime/Engine/Private/GameEngine.cpp#L1898
However, it seems that IsRenderingSuspended() always returns false.
I also saw the cvar t.IdleWhenNotForeground, which does prevent rendering when the window is minimized - but it also stops ticking.
Could you please clarify whether there’s an option to prevent rendering while still allowing ticking when the window is minimized? If not, could you explain why this is the case?
Thanks!
Hi Alexander,
As far as I know, there is no out-of-the-box method to stop the rendering thread from ticking. This is because we need to do some bookkeeping while the process is suspended; otherwise, the engine will run into stability issues. However, there is the GameViewportClient::bDisableWorldRenderingflag, which, if set, allows you to save a lot of system resources while you have the application in the background. Toggling this flag could be a good alternative solution for you. Please let me know your thoughts on this.
Cheers,
Tim
Hello Tim,
Thank you! This flag looks promising.
I took a quick look but didn’t find any OnMinimized delegate or anything similar that we could use to toggle bDisableWorldRendering.
The only potentially relevant thing I came across is:
FGenericApplicationMessageHandler::OnSizeChanged(const TSharedRef< FGenericWindow >& Window, const int32 Width, const int32 Height, bool bWasMinimized = false)
However, I’m not sure how we could override this in our game.
Do you happen to know the proper way to toggle this flag when the app is minimized?
Of course, it’s possible to update this flag every frame based on the IsMinimized value, but that doesn’t seem like an optimal solution.
We do not have a recommended way of doing this. However, I found FPlatformApplicationMisc::IsThisApplicationForeground(), which can check across different platforms if the game’s current process is in the foreground. If you can work that into a custom delegate and then flip bDisableWorldRendering when the app has been pushed into the background, then I would say that is an acceptable solution. Let me know what you think.
Hi Tim,
Thanks for pointing me to this function. I’m not entirely sure how it could be used to create a delegate - since all its implementations seem to simply query the system’s window state, but assuming the performance cost of calling it every frame is negligible, we could try something like this:
`void UBzGameViewportClient::Draw(FViewport* Viewport, FCanvas* SceneCanvas)
{
bDisableWorldRendering = !FPlatformApplicationMisc::IsThisApplicationForeground();
Super::Draw(Viewport, SceneCanvas);
}`where UBzGameViewportClient is a child of UGameViewportClient.
What do think, does this seem like a good solution? Do you see any potential downsides?
Hi Alexander,
To me, this looks like it would likely be fine to use. However, the only way to truly know is for you to test the change on your end. If your tests determine any unwanted side effects, you can reach out again, and we can further discuss refining your solution. Let me know what you think.
Sounds good! I will set the ticket to pending, which will auto-close after one week, but feel free to reply anytime after that in case something comes up.
Cheers,
Tim
Hi Tim, we’ve tested this solution and discovered an issue: on Windows, when the app is not in focus, IsThisApplicationForeground as expected returns false, which causes world rendering to be suspended. However, Instead of freezing the last rendered frame, the window goes completely black, as world rendering stops entirely and no image is displayed. This looks odd, so we’ve decided to suspend rendering only when the app is minimized, rather than when it’s simply in the background.
Here’s what the logic looks like now:
`void UBzGameViewportClient::Draw(FViewport* InViewport, FCanvas* SceneCanvas)
{
#if PLATFORM_DESKTOP
if (const TSharedPtr SharedWindow = GetWindow(); SharedWindow.IsValid())
{
bDisableWorldRendering = SharedWindow->IsWindowMinimized();
}
#endif
Super::Draw(InViewport, SceneCanvas);
}`
Hi Alexander,
Thanks for sharing that. I have marked your comment as the correct solution for suspending rendering while in the background. That way, other folks on this forum can benefit from your answer. If there are any open-ended questions, I am going to close out the ticket.
Hi Tim,
Got it, thanks!
I’ll leave a comment if we run into any issues.
Kind regards