开始
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
时,时间是正常速度;为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
的值不会发生改变。