大家好,我是阿赵。
这期来说一下Unity的TimeScale。
一、前言
Unity提供了Time这个类,来控制时间。其实我自己倒是很少使用这个Time,因为做网络同步的游戏,一般是需要同步服务器时间,所以我比较多是在使用System.DateTime获取系统时间,再定一个时间间隔和服务器同步当前时间,来维持一个客户端和服务器的时间同步。
不过Unity的Time方法也是有比较有用的时候,特别是Time.timeScale时间缩放这个属性,它可以整体的加快或者减慢甚至暂停Unity里面动画播放。
不过这个TimeScale,也是会引起一些问题的,所以在使用之前,必须对它的影响范围做一个详细了解。
二、Demo
TimeScale对Unity的所有动画组件都是起作用的,包括了Animation、Animator、粒子发射器等。接下来看看它对脚本运行的影响。
这里写一个简单的Demo,实际看看TimeScale的变化时,一些我们比较关心的方法调用有什么影响。
using UnityEngine;
public class TestTimeScale : MonoBehaviour
{
private float passTime = 0;
private float fixedPassTime = 0;
private float updateTime = 0;
private float fixedUpdateTime = 0;
private float lateUpdateTime = 0;
private float[] timeArray = new float[] { 0, 0.1f, 1, 3 };
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
passTime += Time.deltaTime;
updateTime += 1;
}
void FixedUpdate()
{
fixedPassTime += Time.fixedDeltaTime;
fixedUpdateTime += 1;
}
private void LateUpdate()
{
lateUpdateTime += 1;
}
void OnGUI()
{
GUILayout.BeginHorizontal();
GUILayout.Box(Time.timeScale + "");
for(int i = 0;i<timeArray.Length;i++)
{
if(OneButton(timeArray[i] + "x"))
{
Time.timeScale = timeArray[i];
}
}
GUILayout.EndHorizontal();
GUILayout.Label("Time.time:"+Time.time);
GUILayout.Label("passTime:" + passTime);
GUILayout.Label("fixedPassTime:" + passTime);
GUILayout.Label("updateTime:" + updateTime);
GUILayout.Label("fixedUpdateTime:" + fixedUpdateTime);
GUILayout.Label("lateUpdateTime:" + lateUpdateTime);
GUILayout.Label("Time.deltaTime:" + Time.deltaTime);
GUILayout.Label("Time.fixedDeltaTime:" + Time.fixedDeltaTime);
GUILayout.Label("Time.fixedTime:" + Time.fixedTime);
GUILayout.Label("Time.fixedUnscaledDeltaTime:" + Time.fixedUnscaledDeltaTime);
GUILayout.Label("Time.realtimeSinceStartup:" + Time.realtimeSinceStartup);
}
private bool OneButton(string content)
{
return GUILayout.Button(content, GUILayout.Width(100), GUILayout.Height(40));
}
}
运行demo,会看到上面有几个调整TimeScale的按钮,分别把TimeScale设置成0、 0.1 、1 、3。然后下面有一些当前数值的变化显示。
三、分析
1、Update类
1.Update
通过观察demo里面的updateTime 可以发现,Update方法的调用频率,是不会受到TimeScale的变化的影响的。
2.FixedUpdate
通过观察demo里面的fixedUpdateTime 可以发现,FixedUpdate方法是受到TimeScale影响的,当TimeScale变成0的时候,值就不会增长了,当TimeScale值变大那时,调用的频率也会变快。
3.LateUpdate
通过观察demo里面的lateUpdateTime 可以发现,LateUpdate方法调用不受TimeScale的影响。
2、时间运行类
1.Time.time
这个时间是从开始游戏到当前帧开始的时间,从demo运行可以看出,这个时间是会受到TimeScale的影响的,当TimeScale变成0的时候,它就不会增长了。
2.Time.fixedTime
这个时间是从游戏开始运行到最后一次FixedUpdate方法调用的时间,从上面可以指定,FixedUpdate是受到TimeScale的影响的,所以,Time.fixedTime同样也会受到TimeScale的影响。
3.Time.realtimeSinceStartup
这个时间是从游戏开始运行到当前的实际时间。从demo可以看出,这个时间是不会受到TimeScale的影响的。所以如果想做一个不受TimeScale影响的计时器,可以使用这个。不过我还是更习惯于使用系统时间。
3、时间间隔类
1.Time.deltaTime
这个时间是从上一帧到当前帧所过的时间。我们经常会使用speedTime.deltaTime来做一些准确限制速度的程序动画。
从demo可以看出,Time.deltaTime是会受到TimeScale的影响的,TimeScale的值越大,Time.deltaTime的值也就越大。所以通过在UpDate方法里面计算speedTime.deltaTime来做动画时,当调大了TimeScale的值,那么动画的速度也会变快。
2.Time.fixedDeltaTime
从demo可以看出,Time.fixedDeltaTime是不会受到TimeScale的影响的,它默认是0.02,然后我们调节TimeScale的值,Time.fixedDeltaTime是不会变化的。
值得注意的是,上面列举的所有参数,都是只读的,但是Time.fixedDeltaTime却是可读写的。这个是非常有意义的事情来的。如果我们使用speedTime.deltaTime来做动画,动画会跟随这TimeScale变快,但如果我们有一部分动画的速度不想跟随着TimeScale变化,那么就可以用speedTime.fixedDeltaTime来计算。而且我们还可以自己调节fixedDeltaTime的值,来单独控制这部分动画的快慢。