可變動幀率(Variable Frame Rate)

在 Unity 中, APP 的每一幀所執行的時間會因為程式碼複雜度或是顯示畫面的複雜度而有所不同,此外也會受到裝置設備的效能影響。

  • 例如:當有一百個角色在螢幕上活動時,每一幀的執行速度會比只有一個角色來的慢,這種可變的速率通常被稱為 每秒幀數 FPS
  • 一般來說 Unity 會嘗試以最快的幀率執行你的 APP。

Update 方法

在 Unity 中,提供了 Update 方法作為每一幀執行我們程式碼的入口(entry point),例如在 Update 中取得使用者的輸入讓遊戲角色向前移動。但是要記住遊戲的幀率是可變的,因此Update調用之間的時間間隔也會變化。


幀率變動對遊戲物件移動速度的影響

下面的程式碼想做的事是把這個遊戲物件平移一段距離,但是幀率(frame rate)是會變動的,因此這個遊戲物件在移動時,它的速度也會變化。
例如:

  • 假設遊戲為每秒 100 幀的速度在執行,那麼 Update 這個方法會執行 100 次,因此這個物件每秒會移動 distancePerFrame 一百次
  • 但是如果因為 CPU 負載變高導致速度下降到 每秒 60 幀的速度在執行的話,那麼這個物件會變為每秒移動 distancePerFrame 六十次
1
2
3
4
5
6
7
public class ExampleScript : MonoBehaviour {
public float distancePerFrame;

void Update() {
transform.Translate(0, 0, distancePerFrame); // 錯誤
}
}

大部分的情況下,這是不好的,因為通常在遊戲中會希望物體是以穩定且可預測的速度移動而不受到幀率影響。


使用 Time.deltaTime 確保一致性

Time.deltaTime 為從上一幀到目前幀之間的時間間隔,以秒為單位。這個屬性通常用於在 Update 方法中進行時間相關的計算
例如,你想要從現開始,經過一秒後做某些動作,可以這樣操作:

1
2
3
4
5
6
7
8
9
10
11
public class ExampleScript : MonoBehaviour {
private float timer = 0f;

void Update() {
timer += Time.deltaTime;
if (timer >= 1f) {
Debug.Log("一秒過去了,某些動作");
timer = 0f;
}
}
}

因此解決上面位移問題的方式是根據每一幀經過的時間來縮放每一幀的移動量,這樣無論幀率如何變化,物體每秒移動的總距離都會保持一致。程式碼如下:

1
2
3
4
5
6
7
8
public class ExampleScript : MonoBehaviour {
// 變數的名稱變為 per second ,這是因為此時不再是依靠幀而是秒了
public float distancePerSecond;

void Update() {
transform.Translate(0, 0, distancePerSecond * Time.deltaTime);
}
}

返回 時間與幀 大綱

評論