Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Autoload v.s. 一般節點
Godot 提供一個功能,可以自動在專案根節點載入節點,讓你能全域存取這些節點,達到單例(Singleton)的效果:請參閱 單例(自動載入)。這些自動載入的節點在你用 SceneTree.change_scene_to_file 切換場景時不會被釋放。
在本篇指南中,我們將學習如何使用 Autoload 功能,以及可以避免使用 Autoload 的一些技巧。
音訊截斷問題
其他的引擎鼓勵使用 Manager 類別,即一種用來管理許多全域存取物件功能的單例。託節點樹與訊號的福,Godot 中提供了許多方法來避免全域狀態。
舉例來說,假設我們在做一個平台遊戲,撿到金幣時需要播放音效,可用 AudioStreamPlayer 節點。但如果 AudioStreamPlayer 正在播放時又被呼叫,新的音效會中斷原本的聲音。
有一種解決方法是撰寫一個全域且自動載入的音訊管理員類別。這個類別要產生一個 AudioStreamPlayer 節點集區,然後在遇到音效播放要求的時候照順序讓每一個 AudioStreamPlayer 來播放。假設我們管這個類別叫 Sound ,則我們在專案任何一個地方都可以通過呼叫 Sound.play("coin_pickup.ogg") 來使用。這樣一來便在短期內解決了問題,但接著會引發更多的問題:
全域狀態 :現在,有一個物件必須要負責所有物件的資料。若
Sound類別發生錯誤,或是沒有可用的 AudioStreamPlayer,則所有呼叫 Sound 的節點都會壞掉。全域存取 :現在所有物件都能從任何地方呼叫
Sound.play(sound_path),所以要找到 Bug 的原因變得更加困難了。全域資源分配 :現在從一開始就有一個
AudioStreamPlayer節點集區,如果數量太少的話便會遇到 Bug,而數量太多的話則會佔用過多的記憶體。
備註
有關全域存取,問題在於,在本例中,任何地方的「所有」程式碼都有可能將錯誤的資料傳給 Sound Autoload。因此,發生問題時要尋找的範圍就變成了整個專案。
如果將程式碼保留在場景中,則只有一兩個程式碼可能會與音訊有關。
相較之下,如果每個場景都在自己內部保佑必要數量的 AudioStreamPlayer 的話,則這些所有的問題便解決了:
每個場景都管理自己的狀態資訊,所以當資料由問題的時候,就只會影響到單一場景。
每個場景都只存取自己的節點。所以當現在出現 Bug 時,就很容易找出是哪個節點的錯。
每個場景都只分配到所需數量的資源。
什麼時候該用 Autoload
GDScript 支援使用 static func 建立 static (靜態) 函式。 當與 class_name 結合使用時,(靜態函式)可以建立輔助函式程式庫,而無需建立實例來呼叫它們。 靜態函式也具有限制,它們不能引用成員變數、非靜態(non-static)函式或 self 。
自 Godot 4.1 起,GDScript 也支援使用 static var 宣告的「靜態」變數。這表示您現在可以在一個類別的不同實例之間共享變數,而不需要建立一個獨立的自動載入節點。
作用域更廣的系統 :若單例管理自己的資訊,且不會存取到其他物件的資料,則建立一個處理廣域資料的系統也不錯。例如,工作或對話系統。
備註
Autoload 並不完全同等與單例 (Singleton)。在 Autoload 中沒有方法可以防止再次實體化一個 Autoload 的節點。只能算是一種能不考慮遊戲節點架構以及目前執行的節點是什麼,就讓節點作為場景樹子節點自動載入的方法,例如,按 F6 鍵。
然後,就能取得自動載入的節點,例如有一個叫 Sound 的 Autoload,則可以呼叫 get_node("/root/Sound") 。