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.

設定 XR

Godot XR 系統簡介

Godot 提供模組化的 XR 系統,將各種 XR 平台的細節抽象化,讓使用者不需直接面對。核心元件為 XRServer,它作為 XR 系統的中央介面,讓使用者可以探索介面並與 XR 系統的各元件互動。

每個支援的 XR 平台都實作為一個 XRInterface。支援的平台清單可在功能一覽頁面 此處 找到。受支援的介面會自行向 XRServer 註冊,並可透過 XRServerfind_interface 方法查詢。找到所需的介面後,可呼叫該介面的 initialize 來進行初始化。

警告

已註冊的介面僅代表該介面可用;若主機系統不支援該介面,初始化可能會失敗並回傳 false。這可能有多種原因,而且不同平台原因各異。可能是使用者尚未安裝所需軟體,或者僅僅是沒有將頭戴式裝置插上。作為開發者,你必須正確處理介面初始化失敗的情況。

由於 XR 輸出有特殊需求,尤其是頭戴裝置需為每隻眼睛提供不同影像,Godot 的 XRServer 會覆蓋算繪系統的多項功能。對於獨立裝置,最終輸出會由 XRInterface 處理,Godot 預設的輸出系統會停用。對於作為第二螢幕的桌面 XR 裝置,可以指定獨立的 Viewport 負責 XR 輸出,讓主 Godot 視窗可用於顯示其他內容。

備註

請注意,僅有一個介面可以負責 XR 裝置的輸出,這稱為主要介面,預設會是第一個被初始化的介面。因此 Godot 目前僅支援單一頭戴裝置的實作。雖然仍可設置次要介面(例如為僅支援 3DOF 的裝置新增追蹤),但這種情況越來越罕見。

幾乎所有 XR 應用程式中都會用到三種 XR 專用節點型別:

  • XROrigin3D 代表你的遊戲空間中心點(雖然這樣說有點過度簡化,但後面會詳細說明)。所有由 XR 平台在實體空間追蹤的物件,都是以這個點為基準定位。

  • XRCamera3D 代表用於 XR 裝置算繪輸出的(立體)相機。這個節點的位置會由 XR 系統自動根據平台提供的追蹤資訊進行更新。

  • XRController3D 代表玩家的控制器,通常有兩個(左、右手各一)。這些節點可以存取控制器的各種狀態,並在玩家按下按鈕時發送訊號。節點位置同樣會由 XR 系統根據平台追蹤資訊自動更新。

還有其他 XR 相關節點,這三個節點也有更多細節,之後會再詳細介紹。

建議採用哪種算繪器

Godot 為專案提供三種算繪器選項:相容性、行動裝置與 Forward+。目前建議桌面 VR 專案使用行動裝置算繪器,而如 Meta Quest 3 這種獨立頭戴裝置則建議使用相容性算繪器。XR 專案雖可使用 Forward+ 算繪器,但相較於前兩者,目前對 XR 的最佳化尚不足。

OpenXR

OpenXR is a new industry standard that allows different XR platforms to present themselves through a standardized API to XR applications. This standard is an open standard maintained by the Khronos Group and thus aligns very well with Godot's interests.

OpenXR 的 Vulkan 實作與 Vulkan 引擎緊密整合,甚至接管部分 Vulkan 系統。這要求在設定 XR 系統前,必須將某些核心圖形功能深度整合至 Vulkan 算繪器中。這也是將 OpenXR 納入核心介面的一大主因。

這也表示,Godot 啟動時必須啟用 OpenXR 才能正確設定。請至專案設定的 XR > OpenXR,確認 Enabled 已勾選。

../../_images/openxr_enabled.webp

此處還有其他與 OpenXR 相關的設定。這些設定在應用程式執行時無法更改。預設值已可正常啟用,如需詳細說明,請參閱 OpenXR 設定

另外,請到專案設定中的 XR > Shaders,勾選 Enabled,以啟用著色器。完成後,請點擊 儲存並重啟 按鈕。

../../_images/xr_shaders.webp

警告

許多後製(後處理)特效尚未更新以支援立體算繪。使用這些效果會造成顯示異常。

建立 XR 場景

每個 XR 應用程式至少需要 XROrigin3DXRCamera3D 節點。大多數情況下還會有兩個 XRController3D,分別代表左手與右手。請注意,相機與控制器節點應為原點節點的子節點。請將這些節點加入新場景,並將控制器節點分別命名為 LeftHandRightHand,場景結構大致如下:

../../_images/xr_basic_scene.webp

警告圖示是預期的,設定控制器後即可消失。請選取左手節點並設定如下:

../../_images/xr_left_hand.webp

右手設定如下:

../../_images/xr_right_hand.webp

目前這些節點都在地板上,執行時會自動定位。為方便開發,可將相機向上移動,令其 y 設為 1.7 ,並將控制器節點分別移至 -0.5, 1.0, -0.5 (左手)與 0.5, 1.0, -0.5 (右手)。

接著,請在根節點(root node)新增腳本,並加入以下程式碼:

extends Node3D

var xr_interface: XRInterface

func _ready():
    xr_interface = XRServer.find_interface("OpenXR")
    if xr_interface and xr_interface.is_initialized():
        print("OpenXR initialized successfully")

        # Turn off v-sync!
        DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)

        # Change our main viewport to output to the HMD
        get_viewport().use_xr = true
    else:
        print("OpenXR not initialized, please check if your headset is connected")

這段程式碼假設你使用的是 OpenXR,如果要改用其他介面,請修改 find_interface 的參數即可。

警告

如上述程式碼所示,我們關閉了垂直同步(v-sync)。使用 OpenXR 時,渲染結果會輸出到 HMD,通常需運作在 90Hz 或更高更新率。若你的螢幕是 60Hz 並啟用垂直同步,則輸出會被限制為每秒 60 影格。

像 OpenXR 這類 XR 介面會自行處理同步。

另請注意,物理引擎預設也是以 60Hz 執行,這可能導致物理表現不流暢。建議將 Engine.physics_ticks_per_second 設為更高的值。

若此時直接運作專案,雖然一切正常,但你會處於一個黑暗世界。因此,請在場景中加入 DirectionalLight3DWorldEnvironment 節點。你也可以暫時在每個控制器節點下新增一個網格實例以方便可視化。請別忘了在世界環境中設定天空。

現在執行專案,你應該會漂浮在空間中,並能自由環顧四周。

備註

雖然傳統的關卡切換方式可用於 XR 應用(即每個關卡都重複此場景結構),但多數開發者會選擇僅建立一次 XR 場景,再以子場景方式載入各關卡。如果你確實在每個場景都複製 XR 設定,務必避免重複執行 initialize,否則依據 XR 介面不同,可能產生不可預期的結果。

在本教學系列其餘部分,我們將以單一場景製作遊戲。