文章

使用 Update() 與 FixedUpdate() 函數

在Unity中,Update()FixedUpdate() 是兩個常用的函數,它們在處理遊戲物體的更新時有不同的應用場景。了解這兩個函數的區別,並在適當的情況下使用它們,是編寫高效且穩定的遊戲邏輯的關鍵。

1. Update() 函數

用途

  • Update() 函數是每一幀都會被調用的函數,用於處理遊戲中與時間無關的更新邏輯。它通常用於處理玩家輸入、非物理驅動的物體運動、動畫控制等。

特點

  • 每幀調用Update() 在每個渲染幀都會被調用。幀率越高,Update() 的調用頻率就越高。
  • 時間間隔不固定:由於幀率不固定,Update() 函數的調用間隔也會隨著每幀的時間而變化。這意味著如果你的遊戲在不同設備上運行,Update() 的執行頻率可能會有所不同。

範例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    public float moveSpeed = 5f;

    void Update()
    {
        // 檢測玩家輸入並移動物體
        float moveX = Input.GetAxis("Horizontal");
        float moveY = Input.GetAxis("Vertical");

        // 計算移動向量
        Vector3 move = new Vector3(moveX, 0f, moveY) * moveSpeed * Time.deltaTime;

        // 移動物體
        transform.Translate(move);
    }
}

在這個範例中,Update() 函數用來檢測玩家輸入並移動遊戲物體。由於移動不涉及物理引擎,使用 Update() 是合適的選擇。

2. FixedUpdate() 函數

用途

  • FixedUpdate() 函數專門用來處理物理更新,如力、碰撞、剛體運動等。它保證在固定的時間間隔內被調用,因此非常適合用來處理物理計算,確保物理行為的一致性和穩定性。

特點

  • 固定時間間隔調用FixedUpdate() 的調用頻率與遊戲的物理時間步(通常為0.02秒)一致,這與幀率無關。
  • 適用於物理運算:因為它在固定的時間間隔內調用,使用 FixedUpdate() 來處理物理運算可以保證物理模擬的一致性,即使在不同的幀率下也是如此。

範例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using UnityEngine;

public class PlayerPhysicsMovement : MonoBehaviour
{
    public float moveForce = 10f;
    private Rigidbody rb;

    void Start()
    {
        // 獲取剛體組件
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        // 檢測玩家輸入並應用力來移動物體
        float moveX = Input.GetAxis("Horizontal");
        float moveY = Input.GetAxis("Vertical");

        // 計算並應用力
        Vector3 force = new Vector3(moveX, 0f, moveY) * moveForce;
        rb.AddForce(force);
    }
}

在這個範例中,FixedUpdate() 用來處理玩家輸入並應用力來移動帶有剛體(Rigidbody)的物體。因為力的應用涉及物理運算,所以 FixedUpdate() 是更合適的選擇。

3. Update() 和 FixedUpdate() 的區別

  • 調用頻率
    • Update() 的調用頻率取決於遊戲的幀率,幀率越高,Update() 調用的次數越多。
    • FixedUpdate() 以固定的時間間隔調用,與幀率無關,通常每秒調用50次(對應0.02秒的物理時間步長)。
  • 適用場景
    • 使用 Update() 來處理非物理相關的遊戲邏輯,如玩家輸入、動畫更新、非物理驅動的物體運動等。
    • 使用 FixedUpdate() 來處理涉及物理引擎的運算,如剛體運動、力的應用、碰撞檢測等。
  • 時間補償
    • Update() 函數內的操作通常需要乘以 Time.deltaTime 來補償幀率的波動,確保物體運動的一致性。
    • FixedUpdate() 自動補償時間步,因此通常不需要額外的時間補償。

4. 組合使用 Update() 和 FixedUpdate()

在一些情況下,你可能需要同時使用 Update()FixedUpdate() 來處理不同的邏輯。例如,在 Update() 中檢測玩家輸入,但在 FixedUpdate() 中應用物理運動:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using UnityEngine;

public class CombinedMovement : MonoBehaviour
{
    public float moveForce = 10f;
    private Rigidbody rb;
    private Vector3 moveInput;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void Update()
    {
        // 在 Update 中檢測玩家輸入
        float moveX = Input.GetAxis("Horizontal");
        float moveY = Input.GetAxis("Vertical");

        moveInput = new Vector3(moveX, 0f, moveY);
    }

    void FixedUpdate()
    {
        // 在 FixedUpdate 中應用力來移動物體
        rb.AddForce(moveInput * moveForce);
    }
}

在這個範例中,Update() 用來檢測玩家的輸入,而 FixedUpdate() 用來處理物理運動,這樣可以在不同幀率下保持物理行為的一致性。

小結

Update()FixedUpdate() 是Unity中處理不同遊戲邏輯的關鍵函數。了解它們的區別和適用場景,並根據遊戲需求選擇適當的函數,可以讓你的遊戲邏輯更加穩定和高效。

本文章以 CC BY 4.0 授權