Unity——Time.timeScale详解

开始

Time.timeScale是个很有意思的属性。先看看官方的介绍(版本2017.2.0f3):

The scale at which the time is passing. This can be used for slow motion effects.

When timeScale is 1.0 the time is passing as fast as realtime. When timeScale is 0.5 the time is passing 2x slower than realtime.

When timeScale is set to zero the game is basically paused if all your functions are frame rate independent.

Except for realtimeSinceStartup, timeScale affects all the time and delta time measuring variables of the Time class.

If you lower timeScale it is recommended to also lower Time.fixedDeltaTime by the same amount.

FixedUpdate functions will not be called when timeScale is set to zero.

总结一下要点:

1、timeScale是时间流逝速度的缩放比例。

2、timeScale为1.0时,时间是正常速度。timeScale为0.5时,时间流逝速度会降为正常速度的一半。

3、timeScale为0时,所有基于帧率的功能都将被暂停。

4、Time.realtimeSinceStartup这个值不受timeScale影响。

5、修改timeScale时,推荐同时以相同比例修改Time.fixedDeltaTime。

6、timeScale为0时,FixedUpdate函数不再执行。

这些介绍是远远不够的,下面实验开始。先贴上代码,建个Cube,重设下transform,把脚本拖上去即可测试:

using UnityEngine;
using System.Collections;

public class TimeScaleDemo : MonoBehaviour
{
    private bool moveDirection = true;
    private bool scaleDirection = true;
    private Renderer rend;

    void Start()
    {
        rend = this.GetComponent<Renderer> ();
        StartCoroutine (ChangeColor ());
    }

    void Update ()
    {
        this.transform.position += Vector3.right * 0.01f * (moveDirection == true ? 1.0f : -1.0f);
        if (this.transform.position.x > 4.0f || this.transform.position.x < 0.0f) {
            moveDirection = !moveDirection;
        }

        this.transform.localScale += Vector3.one * Time.deltaTime * (scaleDirection == true ? 1.0f : -1.0f);
        if (this.transform.localScale.x > 2.0f || this.transform.localScale.x < 1.0f) {
            scaleDirection = !scaleDirection;
        }
    }

    void FixedUpdate ()
    {
        this.transform.rotation = Quaternion.Euler (Vector3.one * 45.0f * Time.fixedDeltaTime) * this.transform.rotation;
    }

    IEnumerator ChangeColor()
    {
        while (true) {
            rend.material.color = Random.ColorHSV ();
            yield return 0;
        }
    }

    void OnGUI ()
    {
        GUI.color = Color.white;

        GUIStyle buttonStyle = new GUIStyle (GUI.skin.button);
        buttonStyle.fontSize = 30;

        GUIStyle labelStyle = new GUIStyle (GUI.skin.label);
        labelStyle.fontSize = 30;

        GUILayoutOption[] options = new GUILayoutOption[]{ GUILayout.Width (300), GUILayout.Height (100) };

        GUILayout.BeginHorizontal ();
        if (GUILayout.Button ("TimeScale = 0", buttonStyle, options) == true) {
            Time.timeScale = 0;
        }
        if (GUILayout.Button ("TimeScale = 0.5", buttonStyle, options) == true) {
            Time.timeScale = 0.5f;
        }
        if (GUILayout.Button ("TimeScale = 1", buttonStyle, options) == true) {
            Time.timeScale = 1;
        }
        if (GUILayout.Button ("TimeScale = 2", buttonStyle, options) == true) {
            Time.timeScale = 2;
        }
        GUILayout.EndHorizontal ();

        GUILayout.Space (50);
        GUILayout.Label ("Time.timeScale : " + Time.timeScale, labelStyle);
        GUILayout.Space (50);
        GUILayout.Label ("Time.realtimeSinceStartup : " + Time.realtimeSinceStartup, labelStyle);
        GUILayout.Space (50);
        GUILayout.Label ("Time.time : " + Time.time, labelStyle);
        GUILayout.Label ("Time.unscaledTime : " + Time.unscaledTime, labelStyle);
        GUILayout.Space (50);
        GUILayout.Label ("Time.deltaTime : " + Time.deltaTime, labelStyle);
        GUILayout.Label ("Time.unscaledDeltaTime : " + Time.unscaledDeltaTime, labelStyle);
        GUILayout.Space (50);
        GUILayout.Label ("Time.fixedTime : " + Time.fixedTime, labelStyle);
        GUILayout.Label ("Time.fixedUnscaledTime : " + Time.fixedUnscaledTime, labelStyle);
        GUILayout.Space (50);
        GUILayout.Label ("Time.fixedDeltaTime : " + Time.fixedDeltaTime, labelStyle);
        GUILayout.Label ("Time.fixedUnscaledDeltaTime : " + Time.fixedUnscaledDeltaTime, labelStyle);
    }
}

如果连代码都懒得复制粘贴,那就看这里的动图:

这里写图片描述

代码说明

1、Cube的平移放在Update里,但是没有跟渲染帧率(deltaTime)关联。

2、Cube的缩放放在Update里,跟渲染帧率(deltaTime)关联。

3、Cube的旋转放在FixedUpdate里,跟物理帧率(fixedDeltaTime)关联。

4、在Start中开启了一个协程用来改变Cube的颜色,其中yield返回值是非时间相关的值。

现象

1、timeScale变化时,平移速度不受影响(但是跟渲染帧率相关),即使timeScale为0,平移依旧进行。

2、timeScale变化时,缩放速度受到影响,timeScale为0时,缩放停止。

3、timeScale变化时,旋转速度受到影响,timeScale为0时,旋转停止。

4、timeScale变化时,颜色改变速度没有受到影响,timeScale为0时,颜色改变依旧进行。

5、GUI上展示了Time类下常用属性的变化,不再描述。

总结Plus

1、timeScale的范围是0到100之间的浮点数,超过此范围时,Unity会给出一条错误信息。这个在实验中没有体现,读者可以自己赋值试试。

2、timeScale 会影响 FixedUpdate的执行速度,但 不会影响 Update、LateUpdate(要测试的话把上函数Update改为LateUpdate即可)的执行速度。timeScale为0时,FixedUpdate完全停止。

3、timeScale 不会影响 Coroutine本身的执行速度。当timeScale为0时,如果Coroutine中yield了某个WaitForSeconds或者WaitForFixedUpdate,那么该Coroutine会在此处停下。如果想要等待一个不受timeScale影响的时间,请用WaitForSecondsRealtime。在实验中将ChangeColor函数中的yield return 0;替换成其他的等待的表达式即可测试。

4、timeScale改变时,会对以下值产生影响:time、deltaTime、fixedTime以及fixedUnscaledDeltaTime。

5、timeScale改变时,不会对以下值产生影响:realtimeSinceStartup、unscaledTime、unscaledDeltaTime、fixedUnscaledTime、fixedDeltaTime。

6、当timeScale为0时,fixedUnscaledTime将停止,但是当timeScale由0变为非0值时,这个值将会有个跳跃,接近于unscaledTime和realtimeSinceStartup。

7、当timeScale改变时,fixedUnscaledDeltaTime会按反比进行改变;例外是当timeScale变为0时,fixedUnscaledDeltaTime的值不会发生改变。

猜你喜欢

转载自blog.csdn.net/serenahaven/article/details/78976628
今日推荐