Unity 中睡眠或暂停的最佳方式,时间精度高

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

我正在做一个Unity项目,需要实现帧显示和处理循环的高精度时序控制。具体来说,我需要帧之间的时间间隔尽可能一致,并且能够以精确到微秒(理想情况下甚至是纳秒)的方式休眠或暂停特定间隔的执行。

在我的应用程序中,通过网络以不规则的间隔接收帧,并且我尝试根据帧的处理时间动态计算每个帧的 toSleep 间隔来控制显示时间。 toSleep 值补偿任何延迟,以便每帧以接近恒定的间隔显示。这是我迄今为止尝试过的:

使用 Thread.Sleep:我尝试过使用 Thread.Sleep 来计算 toSleep 间隔(以毫秒为单位),但很明显 Thread.Sleep 不够精确,尤其是对于较短的持续时间。有时,Thread.Sleep 会超调一毫秒或更多,这会影响帧计时的平滑度。

将 Thread.Sleep 与忙等待循环相结合:由于 Thread.Sleep 仅处理毫秒精度,因此我将其用于粗略计时,然后为最后纳秒添加忙等待循环。这种方法效果更好一些,但是忙等待使 CPU 保持活动状态,这并不理想。

Task.Delay 和协程:我也尝试过 Task.Delay,但它似乎并没有提供比 Thread.Sleep 更好的精度,而且由于我的需求是实时帧更新,所以协程并不合适,因为它们取决于 Unity 的帧速率。

// Main processing loop
void Update()
{
    long startProcessingTime = ProfilerUnsafeUtility.Timestamp;

    // Process frame reception and other operations here...

    long processingTimeNS = ElapsedNanoseconds(startProcessingTime, ProfilerUnsafeUtility.Timestamp);
    long toSleepNS = targetFrameIntervalNS - processingTimeNS;

    if (toSleepNS > 0)
    {
        // Coarse sleep in milliseconds
        int sleepMS = (int)(toSleepNS / 1_000_000);
        if (sleepMS > 0)
        {
            Thread.Sleep(sleepMS);
        }

        // Fine adjustment with busy-wait for remaining nanoseconds
        long remainingNS = toSleepNS % 1_000_000;
        long targetTime = ProfilerUnsafeUtility.Timestamp + remainingNS;
        while (ProfilerUnsafeUtility.Timestamp < targetTime) { /* Busy-wait */ }
    }
}

在 Unity 中实现精确睡眠或暂停功能的最佳方法是什么? Unity中是否还有其他方法可以提供高精度计时而又不会过度消耗CPU资源?

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

这不是 Unity 限制,而是 Windows 限制。 Windows 中的定时器默认分辨率约为 16ms,但具体值将取决于各种其他因素,因此在不同系统上可能会有所不同。此限制也适用于 thread.sleep 以及 task.delay,因为它只是计时器的包装。

高分辨率计时器 Windows API 可用,但据我所知,没有官方的 .net API。因此,您需要编写自己的包装器,或找到第三方包装器。底层硬件是高精度事件计时器,指定最小为 10Mhz 或 100ns,因此这可能是理论极限。

简单的解决方法是 spinnwaiting,但正如您自己所指出的,它确实会消耗 CPU。

© www.soinside.com 2019 - 2024. All rights reserved.