时间膨胀
缘由
最近策划提了一个有意思的需求,就是场景时间膨胀的时候,摄像机不要随时间膨胀变化,当时就懵逼了,游戏中的时间膨胀使用了Time.timeScale,控制了全局都时间膨胀了,不可能在单独处理摄像机啊!
后来,研究了一下 Time.timeScale与Update,FixedUpdate,OnGUI,StartCoroutine之间的关系,终于找到了解决方案。
先说结论:
- 时间膨胀不会影响Update、OnGUI的执行次数
- 时间膨胀会影响FixedUpdate的执行次数
- StartCoroutine函数,如果用WaitForFixedUpdate,那么受时间膨胀影响;如果用WaitForEndOfFrame,那么不受时间膨胀影响。
为啥会影响FixedUpdate的执行次数呢?
其实很简单。如果没有时间膨胀,在Unity中预设值Edit -> Project Settings -> Time -> Fixed Timestep=0.02,那么1秒会执行50次FixedUpdate。时间膨胀之后呢,比如设置TimeScale=0.1,那么需要真实世界的10秒才能达成膨胀世界的1秒,才能跑50次FixedUpdate,对吧,简单吧!
至于StartCoroutine,当选用WaitForFixedUpdate时,跟执行FixedUpdate,是一样的。
数据如下图所示:
![]()
相关的API
// 限制帧数为100Application.targetFrameRate = 100;// 时间膨胀Time.timeScale = 0.1f;// 不受时间膨胀影响的deltaTimeTime.unscaledDeltaTime// 受时间膨胀影响的deltaTimeTime.deltaTime// 协成函数相关yield return new WaitForFixedUpdate()yield return new WaitForEndOfFrame()
附带代码,欢迎指错
using UnityEngine;using System.Collections;public class test : MonoBehaviour { float UpdateTime = 0; float FixedUpdateTime = 0; float GUITime = 0; float CoroutineTime = 0; int UpdateCounter = 0; int FixedUpdateCounter = 0; int GUICounter = 0; int CoroutineCounter = 0; float StartTime = 0; // Use this for initialization void Start() { QualitySettings.vSyncCount = 0; Application.targetFrameRate = 100; Time.timeScale = 0.1f; StartTime = Time.realtimeSinceStartup; StartCoroutine(Func()); } // Update is called once per frame void Update () { UpdateTime += Time.unscaledDeltaTime; UpdateCounter++; } void FixedUpdate() { FixedUpdateTime += Time.deltaTime;// Time.unscaledDeltaTime; FixedUpdateCounter++; } void OnGUI() { GUITime += Time.deltaTime;//Time.unscaledDeltaTime; GUICounter++; GUI.Label(new Rect(10, 10, 1000, 30), "update time=" + UpdateTime + ", counter=" + UpdateCounter); GUI.Label(new Rect(10, 40, 1000, 30), "fixed time=" + FixedUpdateTime + ", counter=" + FixedUpdateCounter); GUI.Label(new Rect(10, 70, 1000, 30), "gui time=" + GUITime + ", counter=" + GUICounter); GUI.Label(new Rect(10, 100, 1000, 30), "coroutine time=" + CoroutineTime + ", counter=" + CoroutineCounter); GUI.Label(new Rect(10, 130, 1000, 30), "real time=" + (Time.realtimeSinceStartup - StartTime)); } IEnumerator Func() { while (true) { CoroutineTime += Time.deltaTime;//Time.unscaledDeltaTime; CoroutineCounter++; //yield return new WaitForEndOfFrame(); yield return new WaitForFixedUpdate(); } }}