时间和帧速率管理

原文链接:https://docs.unity3d.com/Manual/TimeFrameManagement.html

    Update()函数允许你有规律地监视输入和其它事件,并作出正确的行为。例如,你可以移动一个角色当“forward”键被按下时。值得记住的是,当处理基于时间的行为时,比如游戏的帧速率,在Update()函数调用中,既不是连续的,也不是持续一段时间的。

    这样一个例子,考虑持续向前移动移动一个物体的任务,一次一帧。起初,你可能想移动这个物体每一帧以一个固定的距离移动。

using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    public float distancePerFrame;
    
    void Update() {
        transform.Translate(0, 0, distancePerFrame);
    }
}

    可是,给定的帧时间不是恒定不变的,这个物体就会以不规律的速度移动。如果帧时间是10毫秒,那么物体就会以distancePerFrame每秒向前100次。但是,如果帧时间减少到20毫秒(取决于CPU负载),那么就会每秒向前50次,因此移动更少的距离。解决方案是规定在帧时间里移动的大小。你可以从Time.deltaTime的性质中了解更多。

using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    public float distancePerSecond;
    
    void Update() {
        transform.Translate(0, 0, distancePerSecond * Time.deltaTime);
    }
}

    值得注意的是,设置移动,更多的是以distancePerSecond,而不是distancePerFrame。当帧速率改变时,每步移动的大小也会相应的改变,因此,物体的速度也就不会改变。

固定时间步(Fixed Timestep)

    不像主帧的刷新,Unity的物理系统是以固定时间步工作的,这对精确的模拟现实很重要。在物理刷新的一开始,也就是上一个物理刷新结束,Unity设置一个“alarm”,并添加固定时间步到时间里。脚本就会开始计算直到alarm结束。

    你可以从TimeManager中改变固定时间步的大小,你也可以使用Time.FixedDeltaTime的性质从脚本中读取固定时间步。值得注意的是,时间步越小,物理刷新越快,模拟得就更精确,但这会消耗更多的CPU负载。其实,只要你对物理引擎没有更高的要求,你就可能不需要改变默认的时间步。

最大允许时间步

    固定时间步实时地保持物理模拟得准确性,但是它也会导致一些问题。比如在游戏的某个场景使物理模拟得占用过大,同时游戏的帧率也会变得很低。(取决于场景中物体的数量)主帧刷新的过程不得不在规律的物理刷新和如果有许多进程要去做,然后数个物理刷新在一帧中同时发生中设法腾出空间。因此,在一个帧时间中,物体的位置和其他的性质在一帧开始时被冻结,画面能和跟频繁的物理刷新同时出现。

    自然而然的,CPU的自由有限,但是Unity可以选择是你有效地减慢物理时间,使帧处理能跟上。最大允许时间步设置(在Time Manger中)放一个时间量的限制,Unity就会在这段时间里处理物理事件,FixedUpdate在给定的帧刷新中调用。如果一帧的更新时间超过了最大允许时间步,物理引擎就会“停止时间”,使帧的处理更跟上。一旦帧更新结束,物理将会继续,即使从它停止后没有就时间了。这就导致刚体(rigidbodies)不能实时完美运行,但这种减速是轻微的。不管怎样,物理时钟会仍然跟踪它们,即使它们在正常移动。这种物理延迟通常是注意不到的,是一个种接受的与游戏性能的折中。

Time Scale

    对于一些特殊的效果,例如“子弹时间”,有时放慢游戏的速度,便于动画和脚本的反应在降低的帧率下发生。另外,你想完全冻结游戏里的时间,比如在游戏暂停时。Unity有一个Time Scale的属性控制游戏里的时间相对于真实时间的快慢。如果大小设为1.0,那么游戏时间相当于真实时间。如果设为2.0,使游戏时间是真实时间的两倍(动作将会加速)。当设为0.5时,就会将游戏时间速度减半。设为0时会使时间完全停止。值得注意的是,time scale不会真正减慢执行速度但会改变time step,从而改变Update和FixedUpdate函数的Time.deltaTime和Time.fixedDeltaTime。当游戏时间减慢,但deltaTime帧会减少,Update函数会被比平时调用得更频繁。其他的脚本函数不会受time scale的影响,所以在游戏停止时,你可以正常显示GUI。

    Time Manager有一个属性可以让你设置全局time scale,这很方便的从脚本这设值,使用Time.timeScale属性。

using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    void Pause() {
        Time.timeScale = 0;
    }
    
    void Resume() {
        Time.timeScale = 1;
    }
}

捕捉帧率

    一个关于时间管理的特案是你想以视屏的形式记录游戏。因此,保存屏幕画面的任务会花费很多时间,如果你在正常的游戏里企图这样做,游戏的帧率将会大幅下降。这就导致,视屏不能真实反映游戏的情况。

    幸运的是,Unity提供了一个Capture Framerate的属性,它能让你绕过这个问题。当属性值被设为任何一个大于0的数,游戏时间将会减慢,帧刷新会在准确的规则的间隔执行。这些间隔在帧与帧之间等于1/Time.captureFramerate,因此如果你将值设为5,那么刷新就会在一秒钟执行5次。因为对帧率的需求有效地降低,你就有时间在Update函数里保存截屏或执行其他操作。

using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    // Capture frames as a screenshot sequence. Images are
    // stored as PNG files in a folder - these can be combined into
    // a movie using image utility software (eg, QuickTime Pro).
    // The folder to contain our screenshots.
    // If the folder exists we will append numbers to create an empty folder.
    string folder = "ScreenshotFolder";
    int frameRate = 25;
        
    void Start () {
        // Set the playback framerate (real time will not relate to game time after this).
        Time.captureFramerate = frameRate;
        
        // Create the folder
        System.IO.Directory.CreateDirectory(folder);
    }
    
    void Update () {
        // Append filename to folder name (format is '0005 shot.png"')
        string name = string.Format("{0}/{1:D04} shot.png", folder, Time.frameCount );
        
        // Capture the screenshot to the specified file.
        Application.CaptureScreenshot(name);
    }
}

    虽然使用了这种技术的游戏录制功能看起来不错,但游戏可能难以游玩当速度减得很慢时。你可能需要测试一下Time.captureFramerate的值,允许足够的时间来记录,而不会使测试人员的工作过度的复杂。

转载于:https://my.oschina.net/u/3205569/blog/908999

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值