修正抖動、卡頓與輸入延遲

什麼是抖動、卡頓與輸入延遲?

抖動 (jitter)與 卡頓 (stutter)是畫面物件可見運動的兩種不同異常現象,即使遊戲在滿幀率下運作也可能發生,並影響遊戲體驗。這類效應在世界以固定速度、固定方向運動的遊戲(如跑酷或橫向捲軸平台遊戲)中特別明顯。

輸入延遲 和抖動、卡頓無直接關聯,但經常一起被討論。輸入延遲是指玩家用滑鼠、鍵盤、控制器或觸控螢幕操作時,畫面反應所產生的可見延遲。其原因可能來自遊戲程式碼、引擎核心,或外部硬體。輸入延遲在需要滑鼠瞄準的遊戲(如第一人稱射擊)中最為明顯。雖然輸入延遲無法完全消除,但可以用多種方法減少。

如何區分抖動與卡頓

一款在正常幀率下運作且沒有異常現象的遊戲,畫面會相當流暢:

../../_images/motion_normal.gif

出現*抖動*的遊戲會有持續微小晃動的現象:

../../_images/motion_jitter.gif

而出現*卡頓*的遊戲則大致上保持流暢,但每隔幾秒就會*停頓*或*倒退一個影格*:

../../_images/motion_stutter.gif

抖動

抖動可能有許多成因。最典型的是遊戲的 物理更新頻率 (通常為 60 Hz) 與螢幕刷新率不同所致。請先確認你的螢幕刷新率是否不同於 60 Hz。

有時只有部分物件(例如角色或背景)會出現抖動。這通常是因為它們使用不同的時間來源處理(例如某些在 physics 步處理,另一些在 idle 步處理)。

可以在專案設定中啟用 physics interpolation 來緩解這種抖動。物理插值會在物理影格之間對物理物件的變換進行插值,使物理更新更平滑。如此一來,無論影格率或物理更新率為何,物理物件的視覺表現都能保持順暢。

啟用物理插值有一些需要注意的地方。例如在瞬移物件時要特別處理,避免在不希望的情況下,物件在舊位置與新位置之間出現可見的插值。詳情請參閱 物理插值

備註

啟用物理插值會增加依賴物理更新的行為(例如玩家移動)的輸入延遲。對多數遊戲而言,這通常比抖動更可取,但對固定幀率運作的遊戲(例如格鬥或節奏遊戲)需要審慎評估。你可以如 輸入延遲 章節所述,提高物理更新率來補償這個輸入延遲。

卡頓

卡頓可能由多種因素造成。其中一個原因是 CPU 或 GPU 瓶頸導致遊戲無法維持完整幀率。這屬於遊戲內容層面的議題,需要進行 optimization

另一個常見原因是 著色器編譯卡頓。當遊戲中首次出現新的材質或粒子效果時, 需要編譯對應的著色器, 便可能造成卡頓。這類卡頓通常只會在第一次遊玩時發生, 或在顯示卡驅動更新後 (著色器快取失效) 再次出現。

自 Godot 4.4 起,在使用 Forward+ 或 Mobile 渲染器時,引擎會採用「超級著色器 (ubershader)」的方式來盡量避免著色器編譯卡頓。為了讓此方法更有效,你需要在設計場景與資源時,使 Godot 能在場景/資源載入時就蒐集到盡可能多的資訊,而非等到第一次繪製時才取得。詳情請參閱 減少著色器(管線)編譯造成的卡頓

然而,由於 OpenGL 的技術限制,在 Compatibility 渲染器中無法使用 ubershader 的作法。因此,若要避免 Compatibility 渲染器的著色器編譯卡頓,就需要在關卡載入時,將所有網格與視覺效果在鏡頭前生成一個影格,以確保著色器在關卡載入期間就被編譯完畢,而不是在遊戲進行中才發生。你可以在實心的 2D 介面後面執行這個步驟(例如全螢幕的 ColorRect 節點),以免玩家看到。

備註

在支援關閉垂直同步(V-Sync)的平台上,可以在專案設定中停用 V-Sync 以降低卡頓感受,但這會導致畫面撕裂,特別是在低刷新率的螢幕上。若螢幕支援,建議啟用可變更新率(G-Sync/FreeSync),同時保留 V-Sync 開啟。這能在不引入撕裂的情況下緩解某些形式的卡頓。不過,這對於大型卡頓(例如著色器編譯引起的卡頓)並沒有幫助。

強制顯示卡使用最高效能設定檔也能減少卡頓,但會增加 GPU 耗電。

此外,卡頓也可能由底層作業系統引起。以下是各作業系統上與卡頓相關的資訊:

Windows

在 Windows 上,視窗化遊戲容易發生卡頓。情況多半與硬體、驅動版本及同時執行的程序有關(例如開了許多瀏覽器分頁可能使正在執行的遊戲卡頓)。為了緩解這點,Godot 會將遊戲行程優先權提高到「Above Normal」。這能大幅改善,但仍無法完全消除卡頓。

要徹底消除這種情況,需要賦予遊戲成為「Time Critical」的完整權限,但並不建議這麼做。某些遊戲會這樣處理,但整體而言這在 Windows 遊戲中相當常見,而且多數玩家不會用視窗模式遊玩(即使是常以視窗模式遊玩的類型,例如益智遊戲,通常也較少遇到此問題),因此建議接受這個現實。

在全螢幕模式下,Windows 會給予遊戲特殊優先順序,因此卡頓現象極少見。大多數遊戲都是採用這種方式執行。

若您使用輪詢率 1,000 Hz 以上的滑鼠,建議使用最新版 Windows 11,該系統針對高輪詢率滑鼠引起的高 CPU 使用率有相關修正,這些修正在 Windows 10 及更舊版本中並未實作。

小訣竅

遊戲建議使用 Exclusive Fullscreen**(獨佔全螢幕)視窗模式,而非 **Fullscreen,因為後者設計目的是避免 Windows 將視窗誤判為獨佔全螢幕。

Fullscreen 主要用於需要每像素透明度且不希望被作業系統關閉這功能的 GUI 應用程式。它會在螢幕底部保留 1 像素的線條。而 Exclusive Fullscreen 則會真正以螢幕實際尺寸運作,讓 Windows 能降低全螢幕遊戲的抖動與輸入延遲。

Linux

在 Linux 桌面環境下,也可能出現卡頓,這通常與顯示卡驅動程式或視窗合成器有關。有些合成器(例如 KWin)會惡化此問題,可以考慮切換其他合成器進行排除。部分視窗管理器如 KWin、Xfwm 可手動關閉合成,能提升效能,但可能會導致畫面撕裂。

針對由驅動程式或合成器導致的卡頓,除了向相關開發團隊回報問題,無其它解法。在視窗模式下,即使已關閉合成,卡頓情形通常比全螢幕更明顯。

Feral GameMode 可用來於執行特定程式時自動套用最佳化設定(例如強制 GPU 使用高效能模式)。

macOS

一般來說,macOS 基本上不會發生卡頓。不過,近期有部分全螢幕狀態下的卡頓回報(這屬於 macOS 系統本身的問題)。若您的裝置有此現象,請回報給我們。

Android

Android 裝置通常不會發生卡頓與抖動,因為執行中的應用會獲得最高優先權。但仍有些裝置可能出現問題(如舊款 Kindle Fire)。若您在 Android 平臺遇到類似狀況,歡迎回報。

iOS

iOS 裝置通常不太會有卡頓現象,但舊型裝置若升級到新版系統,仍有可能出現問題,這在多數狀況下無法避免。

輸入延遲

專案設定

在支援停用垂直同步的平臺上,可以在專案設定中關閉 V-Sync 以降低輸入延遲,但這樣會導致畫面撕裂,尤其在低刷新率顯示器上。建議讓 V-Sync 作為選項,讓玩家可自行切換。

當使用 Forward+ 或 Mobile 算繪模式時,若已啟用 V-Sync,還能進一步透過「雙緩衝」取代預設的「三緩衝」來降低視覺延遲。自 Godot 4.3 起,可將 Display > Window > V-Sync > Swapchain Image Count 專案設定調整為 2 即啟用雙緩衝。不過,雙緩衝在無法達到螢幕刷新率時(如 CPU/GPU 效能不足),幀率會變得不穩定。例如 60 Hz 螢幕下,若三緩衝時遊戲幀率約 55 FPS,雙緩衝則會瞬間降到 30 FPS,然後再回升至 60 FPS。因此,僅建議在目標硬體能*穩定*輸出滿幀率時,才使用雙緩衝 V-Sync。

提升每秒物理計算次數同樣能降低物理相關的輸入延遲。這在啟用物理內插(即提升平滑度但增加延遲)時更為明顯。您可以將 Physics > Common > Physics Ticks Per Second 設定為高於預設值 60,或於執行時透過腳本設定 Engine.physics_ticks_per_second。若未啟用物理內插,建議設定為螢幕刷新率的倍數(如 120180240),可避免抖動。額外好處是較高的物理幀率能減少穿透和物理不穩定問題。

但增加物理幀率會提升 CPU 使用率,對於物理運算量大的遊戲可能造成效能瓶頸。您可選擇僅在低延遲至關重要時提高物理幀率,或讓玩家依硬體調整。不過,即便您的邏輯程式碼都正確使用 delta,不同的物理幀率還是會導致物理模擬結果出現差異,讓部分玩家產生優勢。因此,競技型多人遊戲不建議讓玩家自行調整物理幀率。

最後,您也可以在腳本中呼叫 Input.set_use_accumulated_input(false),以停用每個算繪影格的輸入緩衝。這樣 _input()_unhandled_input() 會於每次輸入時立即呼叫,而非累積輸入並等到下一影格才處理。停用輸入累積會增加 CPU 使用率,請謹慎使用。

小訣竅

在任何 Godot 專案中,你都可以使用 --disable-vsync command line argument 來強制關閉 V-Sync。自 Godot 4.2 起,也可使用 --max-fps <fps> 設定 FPS 上限(0 代表無上限)。這兩個參數可以同時使用。

針對硬體/作業系統的建議

若您的顯示器支援,建議同時啟用可變刷新率(G-Sync/FreeSync)及 V-Sync,並依照 這篇文章 的建議,將專案設定中的最大幀率限制設為略低於螢幕最大刷新率。例如 144 Hz 螢幕可設為 141。這看似違反直覺,但實際上可確保作業系統無須等待垂直消隱完成,達到與關閉 V-Sync 並限制幀率時*幾乎相同*的輸入延遲(通常僅多出不到 1 毫秒),同時又完全無撕裂。

您可以透過調整 Application > Run > Max FPS 專案設定,或於執行時在腳本設定 Engine.max_fps 來完成。

某些平臺(如 Windows 上的 NVIDIA 控制面板)可以在驅動程式設定中啟用低延遲模式,選擇 Ultra 可以獲得最低延遲(但平均幀率會稍降)。同時強制 GPU 使用最高效能模式,也能進一步減少輸入延遲,但會增加耗電與散熱(風扇噪音)。

最後,請在作業系統顯示設定中,確認您的顯示器已設定為最高刷新率。

同時,請確認您的滑鼠設定為最高輪詢率(遊戲滑鼠通常為 1,000 Hz 或更高)。但輪詢率越高,CPU 負擔也越大,若為低階 CPU,建議設為 500 Hz 較為穩妥。若滑鼠支援多段 DPI ,建議也可 將 DPI 調至最高,遊戲內靈敏度調低,以降低滑鼠延遲

在 Linux 使用 X11 時,若視窗管理器允許(例如 KWin 或 Xfwm),關閉視窗合成可顯著降低輸入延遲。

回報抖動、卡頓或輸入延遲問題

若您回報的抖動或卡頓問題(提出 Issue)並非上述原因,請盡量詳列您的裝置、作業系統、驅動程式版本等資訊,有助於我們進一步協助排除問題。

若您要回報輸入延遲問題,請附上用高速相機(如手機的慢動作錄影)拍攝的影片。影片**必須**同時錄到螢幕與輸入裝置,以便計算從輸入到畫面反應的影格數。請同時註明顯示器刷新率與輸入裝置(特別是滑鼠)的輪詢率。

另外,請根據實際狀況使用正確的名詞(抖動、卡頓、輸入延遲),這有助於我們更快理解您的問題。請附上可重現問題的專案,並盡可能提供螢幕錄影以利說明。