坐在菜单中时减少 Unity 资源使用量

问题描述 投票:0回答:1

我想知道是否有任何方法可以减少 Unity 在表面上不执行任何操作(例如坐在非动画菜单中)时使用的资源量。在现代游戏中,这是总是让我烦恼的事情,而且我知道这也会让其他人烦恼,闲置的游戏使用的资源几乎与实际运行时一样多。

在低级应用程序中,您可以暂停帧更新,直到 Windows 事件触发它们,但这在 Unity 中是不可能的,因为更新循环是在内部触发的。

您可以将目标帧速率设置得较低,但这会使菜单在您单击某些内容时没有响应,即使您在单击时立即将帧速率调高,而且无论如何也不会降低 CPU 使用率。

c# unity-game-engine
1个回答
0
投票

Unity 是一个实时游戏引擎。这意味着它旨在使用尽可能多的资源。所以一般来说,Unity 这样做是正常


它是如何做到的?系统中运行的每个应用程序都在循环中运行。但经典的 UI 应用程序使用操作系统提供的库来获取用户输入。

在 Windows 上,这是底层的 WinAPI。如果您创建 UI 应用程序,您将使用

GetMessage
函数,例如:

while (GetMessage(...) != 0) {
    ...
}

GetMessage
阻止执行,直到收到消息

如果您设计游戏循环,您可以使用

PeekMessage
函数来处理系统消息:

while (true) {
    if(PeekMessage(&msg,0,0,0,PM_REMOVE) {
        ...
    }
    
    ...
}

PeekMessage
不会阻止执行,从而允许循环尽可能频繁地执行。

以这种方式执行循环将导致 CPU 核心 100% 负载。这不是一个好的做法,因此通常使用

std::this_thread::yield();
(C++) 或系统提供的等效项 让其他应用程序在同一核心上执行。换句话说,即使任务管理器显示 100% 使用率,游戏也不会真正利用所有可用的 CPU 时间。

现在,Unity 中的所有内容(包括输入系统)都在该循环中运行,而不接触操作系统。这就是为什么当您降低游戏运行的 FPS 时无法获得正确的输入。

如何处理这个问题:

    最简单的方法是仍然依赖内置设置,即
  1. QualitySettings.vSyncCount

    Application.targetFrameRate 您无法将 FPS 数字减少到 0 或 1,这是不可能的,您可以使用值 60、30 或 15。

    还有一种通过代码手动限制帧速率的方法,用户无法关闭该方法,例如:

    const int _fpsLimit = 60; const double _desiredSecondsPerFrame = 1.0 / _fpsLimit; void Update() { var startOfFrameTicks = DateTime.Now.Ticks; while (true) { Thread.Yield(); // Let's the system to execute something else waiting for CPU time // Then we return back and check whether we need to wait more or exit the loop var currentTicks = DateTime.Now.Ticks; var elapsedTime = TimeSpan.FromTicks(currentTicks - startOfFrameTicks).TotalSeconds; if(elapsedTime >= _desiredSecondsPerFrame) break; } }

  2. Unity 可以“嵌入”到应用程序中。该应用程序可以作为 UI 应用程序来实现。因此,您可以在 Unity 之外创建 UI,并且仅使用 Unity 来运行游戏。
  3. 通过使用

    GetMessage
  4. 实现您自己的 UI 循环,“可能”可以实现相同的效果。它应该在单独的线程中运行,然后触发主线程的更新。这里的问题是如何不干扰 Unity 已有的消息循环,以及如何实际触发它。
  5. 
    
© www.soinside.com 2019 - 2024. All rights reserved.