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.

手動切換場景

有時候你會需要更細緻地控制場景的切換方式。Viewport 的子節點會算繪到它所產生的影像中,即使這些節點並不屬於「目前」場景也一樣。自動載入(Autoload)的節點屬於這一類,同時在執行時動態實例化並加入樹狀結構的場景也是:

var simultaneous_scene = preload("res://levels/level2.tscn").instantiate()

func _add_a_scene_manually():
    # This is like autoloading the scene, only
    # it happens after already loading the main scene.
    get_tree().root.add_child(simultaneous_scene)

要完成流程,將新場景與舊場景交換時,你有多種選擇。從 Viewport 視圖中移除場景的方法有很多,這些方法在操作速度、記憶體消耗,以及資料存取與完整性等方面都各有取捨。

  1. 刪除現有場景。 SceneTree.change_scene_to_file()SceneTree.change_scene_to_packed() 會立即刪除目前場景。你也可以手動刪除主場景,假設根節點名稱為「Main」,可以執行 get_node("/root/Main").free() 來刪除整個場景。

    • 釋放記憶體。

      • 優點:記憶體不再被佔用。

      • 缺點:若要再次回到該場景,必須重新載入到記憶體,這會消耗更多時間與記憶體。如果不需要很快切回原場景,這通常不是問題。

      • 缺點:無法再存取該場景的資料。如果短期內不需要用到這些資料,問題不大。

      • 注意:如果需要保留即將被刪除場景中的資料,可以將其中一個或多個節點重新掛載到其他場景,甚至直接掛載到 SceneTree 上。

    • 處理停止。

      • 優點:沒有節點就沒有運算、物理運算或輸入處理,CPU 可專注處理新場景內容。

      • 缺點:這些節點的運算與輸入處理都不再進行。如果不需要即時的資料更新,問題不大。

  2. Hide the existing scene. By changing the visibility or collision detection of the nodes, you can hide the entire node sub-tree from the player's perspective. Use CanvasItem.hide() to hide a scene and CanvasItem.show() to show it again.

    • 記憶體仍被佔用。

      • 優點:如有需要,仍可存取資料。

      • 優點:不必再移動任何節點即可保留資料。

      • 缺點:更多資料會繼續佔用記憶體,對於像網頁或手機這種對記憶體敏感的平台可能會造成問題。

    • 仍然持續處理。

      • 優點:資料會持續接收處理更新,因此場景內依賴 delta time 或影格資料的內容會持續更新。

      • 優點:節點仍然會是群組的成員(因為群組屬於 SceneTree)。

      • 缺點:CPU 的運算量會分散到多個場景,如果負載過大可能導致畫面更新率降低。建議隨時測試效能,確保目標平台能承受這種負載。

  3. Remove the existing scene from the tree. Assign a variable to the existing scene's root node. Then use Node.remove_child(Node) to detach the entire scene from the tree. To attach it later, use Node.add_child(Node).

    • 記憶體仍被佔用(優缺點與隱藏場景方式相似)。

    • 停止處理(優缺點與完全刪除場景相似)。

    • 優點:這種「隱藏」變體更容易顯示/隱藏場景,只需呼叫 add_child 或 remove_child 方法,而不必追蹤場景的多次變動。這類似於其他引擎裡的遊戲物件啟用/停用功能。

    • 缺點:與單純隱藏場景不同,如果場景內的資料依賴 delta time、輸入、群組或其他來自 SceneTree 的資料,這些內容會變得過時。

有時你可能需要同時存在多個場景,例如在執行時新增自訂單例,或在切換場景時保留資料(將場景加到根節點下)。

get_tree().root.add_child(scene)

另一種情境是使用 SubViewportContainers 同時顯示多個場景。這非常適合在螢幕不同區域算繪不同內容(如小地圖或分割畫面的多人遊戲)。

每種選項都有其最合適的應用時機,因此你必須評估每種方式的效果,選擇最適合自己專案需求的做法。