文档章节

时间和帧速率管理

LIndieGS
 LIndieGS
发布于 2017/05/25 16:05
字数 1695
阅读 29
收藏 0

原文链接: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的值,允许足够的时间来记录,而不会使测试人员的工作过度的复杂。

© 著作权归作者所有

共有 人打赏支持
上一篇: 创建和销毁物体
下一篇: 事件函数
LIndieGS
粉丝 0
博文 9
码字总数 6421
作品 0
程序员
私信 提问
走在网页游戏开发的路上(六)

本文转自吴秦博客园博客,原文链接:http://www.cnblogs.com/skynet/archive/2011/06/11/2078554.html,如需转载请自行联系原作者Flash动画原理 ——动画是将静止的画面变为动态的艺术.实现...

老朱教授
2017/11/26
0
0
业界 | Facebook刚刚定义了一个新的时间单位Flicks,造福程序猿

今天凌晨,Facebook推出了一款新"产品"——Flicks,一种新的时间单位。是的,一个新的时间单位,和“秒”或“分钟”或“小时”一样的时间单位。 Facebook开源官方发推特发布了这一消息 不少人...

阿里云_云栖社区
01/24
0
0
计算机网络之数据链路层

数据链路层功能: 数据链路的建立、维护与拆除;帧包装 帧传输 帧同步;帧的差错恢复 ;流量控制 ; 以太网: 局域网就是以太网;以太网工作在数据链路层; 以太网注意的三个问题:数据的冲突...

闪耀小行星
01/04
0
0
Canvas 入门6 requestAnimationFrame实现动画

本文学习资源来自《HTML5 Canvas核心技术 图形、动画与游戏开发》 尽量不要使用setInterval和setTimeout来实现动画,而应该使用requestAnimationFrame()方法来让浏览器自行决定帧速率。 由于...

xundh
2017/12/07
0
0
交换机性能指标

一般厂商标称交换机性能会包含两个指标,一是交换背板(或者叫交换矩阵),一是包转发速率。 交换背板是指交换机内部架构的带宽,单位是bps,比如说super720的交换背板能力为720Gbps。这是引...

余二五
2017/11/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

MySQL Replication 梳理详解

MySQL Replication 1 MySQL5.5以前的复制 异步、SQL线程串行化回放 MySQL内建的复制功能是构建大型,高性能应用程序的基础。主服务器将更新写入二进制日志文件,从服务器重新执行一遍来实现的...

PeakFang-BOK
今天
1
0
.NET Core & ConsoleApp & appsettings.json

准备 Visual Studio 2017 .NET Core 2.1 新建控制台应用(.NET Core) 默认的 Program.cs // Program.csusing System;namespace ConsoleApp1{ class Program { static voi......

taadis
今天
2
0
结合lucene谈谈日期的压缩问题

说起日期值的压缩,一般容易想到的办法是将日期转化成long类型,然后再通过变长整形进行压缩,我算了一下按照毫秒来算最多占用5个字节(可以通过“谈谈变长整型”中的表查看),确实节省了部...

FAT_mt
今天
1
0
导出私有函数与私有变量

在Go语言中, package中包含函数与变量通过identifier的首字母是否大写来决定它是否可以被其它package所访问。当一个函数或变量名称为小写字母时,默认是无法被其他package引用的. 有没有办法...

xtof
今天
2
0
new Date() 在Safari下的 Invalid Date问题

问题复现 var timeStr = '2018-11-11 00:00:00';var time = new Date(timeStr);// error: Invalid Date... 在safari浏览器下,time为Invalid Date, 导致后面代码执行错误; 其他浏览器诸...

会写代码的husky
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部