Time.timeScale 時間縮放
在 Unity 中,利用 Time.timeScale=0 可以暫停游戲,Time.timeScale=1 恢復正常,
但這是作用於整個游戲的設置,不單單是當前的場景,所以在需要的時候重置回 Time.timeScale=1。
當然,也可以使用 Time.timeScale 來做游戲1倍、2倍的整體加速,以及0.5倍的整體減速。
Time.timeScale 影響因素
-
timeScale 不影響 Update 和 LateUpdate,會影響 FixedUpdate
-
timeScale 不影響 Time.realtimeSinceStartup,會影響 Time.timeSinceLevelLoad 和 Time.time
-
timeScale 不影響 Time.fixedDeltaTime 和 Time.unscaleDeltaTime,會影響 Time.deltaTime
將 Time.timeScale 設置為 0 會暫停所有和幀率無關的事情:
這些主要是指所有的物理事件和依賴時間的函數、剛體力和速度等,而且 FixedUpdate (不是Update)會受到影響,會被暫停,即 timeScale =0 時將不會調用 FixedUpdate 函數。
但是,Update 和 LateUpdate 函數本身的執行是不會受 Time.timeScale 影響的。
Update 依賴的是機器,它調用的次數和你機器渲染的速度一樣(一些特殊情況除外);性能高的機器,幀率高,Update 函數執行次數也就多。
因此,當使用Time.timeScale = 0 時,所有和時間有關的事情都被暫停了。因為 Time.timeScale 為 0 時,Time.deltaTime 將為 0。
這也就意味着,如果你使用 Time.deltaTime 來控制旋轉和位移等屬性,那么 Time.timeScale = 0 也將使這些物體停止運動。
所以游戲看起來是被凍結了,但是,我們的游戲仍在渲染,也就是說 Update 函數仍在執行。
Time.timeScale 影響測試
1 using UnityEngine; 2 3 public class TimeScaleTest : MonoBehaviour 4 { 5 void Update() 6 { 7 if (Input.GetKeyDown(KeyCode.P)) Time.timeScale = 0; 8 if (Time.timeScale == 0) 9 { 10 print("Update"); 11 12 print("Time.time:" + Time.time); 13 print("Time.timeSinceLevelLoad:" + Time.timeSinceLevelLoad); 14 print("Time.realtimeSinceStartup:" + Time.realtimeSinceStartup); 15 16 print("Time.deltaTime:" + Time.deltaTime); 17 print("Time.fixedDeltaTime:" + Time.fixedDeltaTime); 18 print("Time.unscaledDeltaTime:" + Time.unscaledDeltaTime); 19 } 20 } 21 22 void LateUpdate() 23 { 24 if (Time.timeScale == 0) print("LateUpdate"); 25 } 26 27 void FixedUpdate() 28 { 29 if (Time.timeScale == 0) print("FixedUpdate"); 30 } 31 }
分別對里面的部分代碼進行注釋,測試結果如下:
當 timeScale 等於 0 時:
Update 和 LateUpdate 可以執行,FixedUpdate 不能執行
Time.realtimeSinceStartup 依然在增加,Time.timeSinceLevelLoad 和 Time.time 都沒有變化
Time.fixedDeltaTime 不變,Time.deltaTime 變為 0,Time.unscaleDeltaTime 就像游戲正常速度運行下的 Time.deltaTime
總結
當想代碼受 timeScale 控制時(如暫停、加速),可以把代碼放在 FixedUpdate 中,又或者跟 Time.time 或 Time.deltaTime 扯上關系;
否則,可以用 Time.realtimeSinceStartup(類似正常狀態下的Time.time) 和 Time.unscaleDeltaTime(類似正常狀態下的Time.deltaTime)。
如果游戲暫停以后想在暫停界面上繼續播放一些不受 Time.timeScale 影響的動畫或者粒子特效,就要用 Time.realtimeSinceStartup 去單獨恢復他們,還有聲音部分也需要單獨恢復 timeScale。
當然也可以放棄 Time.deltaTime 方法,自己實現兩個函數:OnPauseGame 和 OnResumeGame。這種方法擴展性強,但是寫起來可能會比較繁瑣。
*** | 以上內容僅為學習參考、學習筆記使用 | ***