Add FPS limit and pause option when game is unfocused
This commit is contained in:
@@ -43,6 +43,18 @@ public:
|
||||
API_FIELD(Attributes="EditorOrder(20), Limit(0.1f, 1000.0f, 0.01f), EditorDisplay(\"General\")")
|
||||
float MaxUpdateDeltaTime = 0.1f;
|
||||
|
||||
/// <summary>
|
||||
/// Limits maximum game framerate when application window loses focus. Use 0 to disable this feature.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(100), EditorDisplay(\"Unfocused\")")
|
||||
float UnfocusedMaxFPS = 30;
|
||||
|
||||
/// <summary>
|
||||
/// Enables pausing game when application window loses focus.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(110), EditorDisplay(\"Unfocused\")")
|
||||
bool UnfocusedPause = false;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use.
|
||||
|
||||
@@ -40,15 +40,11 @@
|
||||
#include "Engine/Scripting/ManagedCLR/MClass.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MMethod.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MException.h"
|
||||
#include "Engine/Core/Config/PlatformSettings.h"
|
||||
#endif
|
||||
|
||||
namespace EngineImpl
|
||||
{
|
||||
bool IsReady = false;
|
||||
#if !USE_EDITOR
|
||||
bool RunInBackground = false;
|
||||
#endif
|
||||
String CommandLine = nullptr;
|
||||
int32 Fps = 0, FpsAccumulatedFrames = 0;
|
||||
double FpsAccumulated = 0.0;
|
||||
@@ -168,9 +164,6 @@ int32 Engine::Main(const Char* cmdLine)
|
||||
Platform::BeforeRun();
|
||||
EngineImpl::InitMainWindow();
|
||||
Application::BeforeRun();
|
||||
#if !USE_EDITOR && (PLATFORM_WINDOWS || PLATFORM_LINUX || PLATFORM_MAC)
|
||||
EngineImpl::RunInBackground = PlatformSettings::Get()->RunInBackground;
|
||||
#endif
|
||||
LOG_FLOOR();
|
||||
LOG_FLUSH();
|
||||
Time::Synchronize();
|
||||
@@ -353,20 +346,8 @@ void Engine::OnUpdate()
|
||||
|
||||
UpdateCount++;
|
||||
|
||||
const auto mainWindow = MainWindow;
|
||||
|
||||
#if !USE_EDITOR
|
||||
// Pause game if window lost focus and cannot run in a background
|
||||
bool isGameRunning = true;
|
||||
if (mainWindow && !mainWindow->IsFocused())
|
||||
{
|
||||
isGameRunning = EngineImpl::RunInBackground;
|
||||
}
|
||||
Time::SetGamePaused(!isGameRunning);
|
||||
#endif
|
||||
|
||||
// Determine if application has focus (flag used by the other parts of the engine)
|
||||
HasFocus = (mainWindow && mainWindow->IsFocused()) || Platform::GetHasFocus();
|
||||
HasFocus = (MainWindow && MainWindow->IsFocused()) || Platform::GetHasFocus();
|
||||
|
||||
// Simulate lags
|
||||
//Platform::Sleep(100);
|
||||
|
||||
@@ -6,12 +6,29 @@
|
||||
#include "Engine/Platform/Platform.h"
|
||||
#include "Engine/Core/Config/TimeSettings.h"
|
||||
#include "Engine/Serialization/Serialization.h"
|
||||
#if !USE_EDITOR
|
||||
#include "Engine/Engine/Engine.h"
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
bool FixedDeltaTimeEnable;
|
||||
float FixedDeltaTimeValue;
|
||||
float MaxUpdateDeltaTime = 0.1f;
|
||||
#if USE_EDITOR
|
||||
constexpr bool _gamePausedUnfocsed = false;
|
||||
#define GetFps(fps) fps
|
||||
#else
|
||||
bool _gamePausedUnfocsed = false;
|
||||
float UnfocusedMaxFPS = 0.0f;
|
||||
bool UnfocusedPause = false;
|
||||
float GetFps(float fps)
|
||||
{
|
||||
if (UnfocusedMaxFPS > 0 && !Engine::HasFocus && fps > UnfocusedMaxFPS)
|
||||
fps = UnfocusedMaxFPS;
|
||||
return fps;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Time::_gamePaused = false;
|
||||
@@ -52,15 +69,16 @@ void TimeSettings::Apply()
|
||||
Time::DrawFPS = DrawFPS;
|
||||
Time::TimeScale = TimeScale;
|
||||
::MaxUpdateDeltaTime = MaxUpdateDeltaTime;
|
||||
#if !USE_EDITOR
|
||||
::UnfocusedMaxFPS = UnfocusedMaxFPS;
|
||||
::UnfocusedPause = UnfocusedPause;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Time::TickData::Synchronize(float targetFps, double currentTime)
|
||||
{
|
||||
OnReset(targetFps, currentTime);
|
||||
Time = UnscaledTime = TimeSpan::Zero();
|
||||
DeltaTime = UnscaledDeltaTime = targetFps > ZeroTolerance ? TimeSpan::FromSeconds(1.0f / targetFps) : TimeSpan::Zero();
|
||||
LastLength = static_cast<double>(DeltaTime.Ticks) / TimeSpan::TicksPerSecond;
|
||||
LastBegin = currentTime - LastLength;
|
||||
LastEnd = currentTime;
|
||||
NextBegin = targetFps > ZeroTolerance ? LastBegin + (1.0f / targetFps) : 0.0;
|
||||
}
|
||||
|
||||
@@ -115,7 +133,7 @@ void Time::TickData::OnTickEnd()
|
||||
void Time::TickData::Advance(double time, double deltaTime)
|
||||
{
|
||||
float timeScale = TimeScale;
|
||||
if (_gamePaused)
|
||||
if (_gamePaused || _gamePausedUnfocsed)
|
||||
timeScale = 0.0f;
|
||||
LastBegin = time;
|
||||
UnscaledDeltaTime = TimeSpan::FromSeconds(deltaTime);
|
||||
@@ -194,9 +212,11 @@ void Time::SetGamePaused(bool value)
|
||||
{
|
||||
if (_gamePaused == value)
|
||||
return;
|
||||
|
||||
_gamePaused = value;
|
||||
if (_gamePausedUnfocsed)
|
||||
return;
|
||||
|
||||
// Reset ticking
|
||||
const double time = Platform::GetTimeSeconds();
|
||||
Update.OnReset(UpdateFPS, time);
|
||||
Physics.OnReset(PhysicsFPS, time);
|
||||
@@ -249,7 +269,24 @@ void Time::Synchronize()
|
||||
|
||||
bool Time::OnBeginUpdate(double time)
|
||||
{
|
||||
if (Update.OnTickBegin(time, UpdateFPS, MaxUpdateDeltaTime))
|
||||
#if !USE_EDITOR
|
||||
// Pause game if window lost focus (based on game settings)
|
||||
bool gamePausedUnfocsed = !Engine::HasFocus && UnfocusedPause;
|
||||
if (gamePausedUnfocsed != _gamePausedUnfocsed)
|
||||
{
|
||||
_gamePausedUnfocsed = gamePausedUnfocsed;
|
||||
if (!gamePausedUnfocsed)
|
||||
{
|
||||
// Reset ticking
|
||||
const double time = Platform::GetTimeSeconds();
|
||||
Update.OnReset(UpdateFPS, time);
|
||||
Physics.OnReset(PhysicsFPS, time);
|
||||
Draw.OnReset(DrawFPS, time);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Update.OnTickBegin(time, GetFps(UpdateFPS), MaxUpdateDeltaTime))
|
||||
{
|
||||
Current = &Update;
|
||||
return true;
|
||||
@@ -259,7 +296,7 @@ bool Time::OnBeginUpdate(double time)
|
||||
|
||||
bool Time::OnBeginPhysics(double time)
|
||||
{
|
||||
if (Physics.OnTickBegin(time, PhysicsFPS, _physicsMaxDeltaTime))
|
||||
if (Physics.OnTickBegin(time, GetFps(PhysicsFPS), _physicsMaxDeltaTime))
|
||||
{
|
||||
Current = &Physics;
|
||||
return true;
|
||||
@@ -269,7 +306,7 @@ bool Time::OnBeginPhysics(double time)
|
||||
|
||||
bool Time::OnBeginDraw(double time)
|
||||
{
|
||||
if (Draw.OnTickBegin(time, DrawFPS, 1.0f))
|
||||
if (Draw.OnTickBegin(time, GetFps(DrawFPS), 1.0f))
|
||||
{
|
||||
Current = &Draw;
|
||||
return true;
|
||||
|
||||
@@ -43,8 +43,10 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
|
||||
|
||||
/// <summary>
|
||||
/// Enables game running when application window loses focus.
|
||||
/// [Deprecated in v1.12]
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(1010), DefaultValue(false), EditorDisplay(\"Other\", \"Run In Background\")")
|
||||
DEPRECATED("Use UnfocusedPause from TimeSettings.")
|
||||
bool RunInBackground = false;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -40,8 +40,10 @@ API_CLASS(Sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
|
||||
|
||||
/// <summary>
|
||||
/// Enables game running when application window loses focus.
|
||||
/// [Deprecated in v1.12]
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(1010), EditorDisplay(\"Other\", \"Run In Background\")")
|
||||
DEPRECATED("Use UnfocusedPause from TimeSettings.")
|
||||
bool RunInBackground = false;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -43,8 +43,10 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
|
||||
|
||||
/// <summary>
|
||||
/// Enables game running when application window loses focus.
|
||||
/// [Deprecated in v1.12]
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(1010), DefaultValue(false), EditorDisplay(\"Other\", \"Run In Background\")")
|
||||
DEPRECATED("Use UnfocusedPause from TimeSettings.")
|
||||
bool RunInBackground = false;
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user