目录

Unity - Time

# 要点

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 代码说明

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类下常用属性的变化,不再描述。

# 总结

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的值不会发生改变。

# 劣质时停练习

目的:尝试让物体顺时针旋转,每5秒切换一次速度,如开始时一切正常,跑五秒后速度减慢至原本的20%

    public double timeScale = 0;
    public bool sw = true;
    private void Update()
    {
        GameObject.Find("B1").transform.Rotate(0, 100 * (Time.deltaTime), 0);
        print(timeScale);
        if (timeScale > 5) //头两个if用于控制数值边界
        {
            timeScale = 5;
            sw = false;
        }
        else if (timeScale < 0)
        {
            timeScale = 0;
            sw = true;
        }
        else if (timeScale >= 0 && sw)
        {
            Time.timeScale = 1;
            timeScale += Time.deltaTime;
        }
        else
        {
            Time.timeScale = 0.2f;
            timeScale -= Time.deltaTime/Time.timeScale;//重点!由于Time.timeScale会影响deltaTime的运行结果,因此需要除以对应百分比恢复至正常的deltaTime数值!
            
        }

    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

之所以说劣质,是因为这种时停效果会把整个游戏的时间都放慢,对于实际游戏中的玩家而言十分鸡肋(毕竟时停就是给玩家争取额外操作空间和提高爽感的。。),可能可以用于过场动画?如果不想影响玩家,网上提出用Time.realtimeSinceStartup解决问题,但具体操作目前还没试过。

上述的代码中,提到的重点区域,其实能用一个更好的值去代替 —— Time.unscaledDeltaTime 该值能确保得到的deltaTime不受timeScale影响

最近更新
01
基本知识
07-18
02
卷积神经网络识别图像
07-18
03
损失函数
07-18
更多文章>