unity 中文_在Unity中实现准确的帧率

你是否想过,Unity可以遵循准确的帧率,甚至遵循外部时钟源即Genlock同步锁相呢?

本文将介绍Unity如何在本地维持帧率,以及如何添加用户代码来严格控制该过程。该功能在类似于严格同步Unity和其它设备的播音室等环境中非常重要。

ea7ed23cc3aa2bcb30d7ccc6e6953e15.png

通常,Unity项目会尝试着以尽可能快的速度运行。每一帧都会尽快渲染,这通常会受限于显示设备的刷新速率。

控制帧率最简单的方法是:明确设置QualitySettings.vSyncCount,使渲染过程发生的间隔和显示设备的刷新速率相关。

例如:对于频率为60Hz的显示器,设置vSyncCount=2会使Unity以30fps的帧率同步于显示器进行渲染。这样会使帧率限制为显示器刷新速率的大约数值,所以无法提供足够粒度化的控制

另一个简单的解决方法是:设置QualitySettings.vSyncCount=0,并使用Application.targetFrameRate设置独立于显示器刷新速率的帧率目标

通过这样的设置,Unity会将渲染循环限制为约等于该速率。但需要注意,因为此时Unity不再同步于显示器进行渲染,所以可能会出现图像撕裂现象。该方法会消耗较低性能,以避免使用不必要的CPU资源,但缺点是可能无法为每个用例实现所需的精度

不必担心,协程可以帮助你提高精度。我们不必使用Unity内置帧率限制功能,而是通过脚本代码自己控制帧率。

为此,我们必须设置QualitySettings.vSyncCount=0,把Application.targetFrameRate设为非常大的数值,从而让Unity尽可能快的运行项目,然后使用WaitForEndOfFrame协程,通过使下一帧仅在我们允许时才开始渲染,准确的把速度减慢为目标速率。

为了准确执行操作,我们建议结合使用Thread.Sleep,从而适当的延迟Unity渲染循环,避免消耗过多CPU资源,然后在最后几毫秒内调整CPU,同时检查允许下一帧开始渲染的合适时间。

如果要协调Unity帧率和外部时间即Genlock同步锁相,我们应该在收到外部同步信号时立即跳出CPU旋转循环。

using System.Collections;

using System.Threading;

using UnityEngine;

public class ForceRenderRate : MonoBehaviour

{

    public float Rate = 50.0f;

    float currentFrameTime;

    void Start()

    {

        QualitySettings.vSyncCount = 0;

        Application.targetFrameRate = 9999;

        currentFrameTime = Time.realtimeSinceStartup;

        StartCoroutine("WaitForNextFrame");

    }

    IEnumerator WaitForNextFrame()

    {

        while (true)

        {

            yield return new WaitForEndOfFrame();

            currentFrameTime += 1.0f / Rate;

            var t = Time.realtimeSinceStartup;

            var sleepTime = currentFrameTime - t - 0.01f;

            if (sleepTime > 0)

                Thread.Sleep((int)(sleepTime * 1000));

            while (t < currentFrameTime)

                t = Time.realtimeSinceStartup;

        }

    }

}

最后一点,如果想要协调时间和外部时钟源,我们可能也想让Unity的内部游戏时间以相同的速度进行,而不是遵循CPU时间,那样会随着时间相对于外部时钟源发生变化。我们可以通过设置Time.captureFramerate为外部时间的相同速率来实现。

例如:如果外部的Genlock同步锁相信号运行在60fps,我们可以设置CaptureFramerate为60,这样无论现实中经过了多少时间。都会使Unity允许帧之间渲染间隔为游戏时间每秒的1/60,

在Unity 2019.2 Beta中,我们可以通过设置Time.captureDeltaTime,来设置采集帧率的浮点值。对于旧版Unity,如果外部信号不以整数速率运行,例如:速率为59.94。我们可以变化每帧渲染时的CaptureFramerate值,为时间变化实现理想的平均速率。

fae5fd0456fd3a665e2717b210a01ddb.png

我们在GitHub上提供了用于验证上述概念方法的Unity项目,请访问:

https://github.com/Unity-Technologies/GenLockProofOfConcept

我们可以在ForceRenderRate.cs脚本中找到使用WaitForEndFrame协程对帧率进行准确控制的方法,也可以在GenLockedRecorder.cs脚本查看更加复杂的示例,即模仿外部Genlock同步锁相的示例。

虽然Unity不原生支持任何特定厂商的Genlock同步锁相实现,但前面提到的第二个示例是很好的起点,便于集成提供该功能的第三方SDK。

友情提醒:上述所有方法会在部分Unity Standalone Player构建时取得最稳定的帧率,虽然它们在Unity编辑器内的运行模式下有效,但你随时都有可能遇到短暂的帧率波动现象。

参考资料

同步锁相:

https://en.wikipedia.org/wiki/Genlock

V Sync Count垂直同步数文档:

https://docs.unity3d.com/Manual/class-QualitySettings.html#Other

Thread.Sleep:

https://docs.microsoft.com/en-us/dotnet/api/system.threading.thread.sleep

小结

Unity如何在本地维持帧率就介绍到这里,更多Unity功能介绍,尽在Unity Connect平台(Connect.unity.com)。

下载Unity Connect APP,请点击此处。 观看部分Unity官方视频,请关注B站帐户:Unity官方。

推荐阅读

Project Tiny C# 预览版现已推出

Unite 2019 |《球球大作战》优化之路(下)

Unite 2019 |《球球大作战》优化之路(上)

Adaptive Performance:高品质画面呈现与流畅稳定帧率的二者兼得

针对Linux系统的Unity编辑器介绍

使用Unity 2019.1中的Timeline Signals

Unite 2019 | Unity中的实时光线追踪技术剖析

使用Unity 2019.1中的Timeline Signals

有奖调查

Unity Hub 2.0中文版以及Unity中文版文档已发布,请参与有奖调查,反馈你的意见,以便我们进一步改进。更多详情,请访问此处。

53720a98ee68c098e7ae4f15fedad83b.png

喜欢本文,请点击“在看”

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值