Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

3D 文字

前言

專案中不僅會要在 HUD 中使用文字,有時也會需要把文字作為 3D 場景的一部分。Godot 為此提供了兩種方法。Label3D 節點以及 MeshInstance 節點的文字網格。

此外,Godot 還可以根據相機上 3D 點的位置來定位控制節點。在Label3D 和 TextMesh 不夠靈活的情況下,這可以用作「真正」3D 文字的替代方案。

也參考

除了這份說明文件,你可能也會想看看 Godot Demo 專案

若欲檢視範例專案,請參考作業系統示範專案: https://github.com/godotengine/godot-demo-projects/tree/master/misc/os_test

Label (標齊)

../../_images/label_3d.png

Label3D 與標籤節點行為類似,只不過是換到了 3D 空間中。與標籤節點不同,它是不會繼承 GUI 主題屬性的。不過,還是可以自訂外觀的,使用的也是和控制項節點同樣的 DynamicFont 和 BitmapFont 子資源。

優勢

  • Label3D 的產生速度比 TextMesh 更快。雖然兩者都使用快取機制僅渲染一次新字形,但 Label3D 的(重新)產生速度仍然更快,尤其是對於長文字。這可以避免在低階 CPU 或行動裝置上玩遊戲時出現卡頓。

  • Label3D 可以使用點陣字形和動態字型(有或沒有 MSDF(多通道符號距離字型)或 mipmap)。與 TextMesh 相比,這使得它在這方面更加靈活,特別是對於渲染具有自相交輪廓的字形。

也參考

請參閱 doc_gui_using_fonts 以了解設定字型匯入的指南。

限制

Label3D 和 3D 環境的互動很少,著色旗標啟用時能夠接受光照、被光源著色,但即便 GeometryInstance3D 節點打開了陰影投射,它也不會投射陰影。這是因為該節點是一個帶透明紋理的四邊形網格(每個四邊形一個字形),有著和 Sprite3D 一樣的限制。詳情請參閱:ref:這個頁面 <doc_3d_rendering_limitations_transparency_sorting>

這可以透過將 Label3D 的透明度模式設為 Alpha Cut 來緩解,但代價是文字渲染不太流暢。 Opaque Pre-Pass 透明度模式可以保持文字平滑度,同時允許 Label3D 投射陰影,但一些透明度排序問題仍然存在。

有關詳細信息,請參閱 3D 渲染限制頁面中的透明度排序 <doc_3d_rendering_limitations_transparency_sorting>` 部分。

下一步

../../_images/text_mesh.png

TextMesh(文字網格)資源和 Label3D 類似,都能夠在 3D 場景中顯示文字,使用的是相同的字形子資源。但 TextMesh 生成的不是透明四邊形,而是代表字形輪廓的 3D 網格,具有和網格一樣的屬性。因此,TextMesh 預設是開啟著色的,會自動在環境中投射陰影。TextMesh 也可以設定材質(包括自訂著色器)。

這是為網格應用紋理的範例。你可以使用下面的紋理作為生成網格 UV 貼圖的參考:

../../_images/text_mesh_texture.png ../../_images/text_mesh_textured.png

優勢

相對於 Label3D 而言,TextMesh 有以下優點:

  • TextMesh 可以使用紋理來修改文字各個面的顏色。

  • TextMesh 幾何體具有深度,字形看上去是 3D 的。

  • TextMesh 可以使用自訂的著色器,而 Label3D 無法使用。

限制

有幾點需要注意:

  • 沒有內建的輪廓支援,而 Label3D 支援。但是可以使用自訂著色器模擬。

  • 僅支援動態字形(.ttf.otf.woff.woff2)。不支援 .fnt.font 格式的點陣字型。

  • 無法正確渲染輪廓自相交的字形。如果使用從 Google Fonts 等處下載到的字形時出現渲染問題,請嘗試改為從作者的官方網站下載。

投影 Label 節點(或者其他 Control 節點)

還有最後一種設定起來更麻煩的解決方案,但是靈活性更高:將 2D 節點投影到 3D 空間中。做法是在腳本的 _process() 函式中使用 Camera3D 節點的 unproject_position 的返回值。使用這個返回值來設定 Control 節點的 position 屬性。

若欲檢視範例專案,請參考作業系統示範專案: https://github.com/godotengine/godot-demo-projects/tree/master/misc/os_test

優勢

  • Label、RichTextLabel 等任何 Control 節點,甚至 Button 這樣的節點都可以用這種方法。這樣就能夠實作強大的格式和 GUI 互動。

  • 基於腳本的做法能夠在定位方面做到最大的自由度。例如,這樣就能夠在超出螢幕範圍後將 Control 吸附到螢幕的邊緣(用於在遊戲中實作 3D 標記)。

  • Control 主題仍然有效。這樣實作自訂專案全域的設定就更方便。

限制

  • 投影的 Control 無法以任何形式被 3D 幾何體遮擋。目標位置被遮擋時,你可以借助 RayCast 將該控制項完全隱藏,但是無法實作位於牆壁後面時只隱藏部分區域的效果。

  • 可以根據距離調整 Control 的 scale 屬性,從而調整文字的大小,但是需要手動縮放。Label3D 和 TextMesh 會自動處理,但是靈活性不足(無法設定最小/最大的文字像素大小)。

  • 腳本中必須考慮處理解析度和寬高比的變化,這可能具有挑戰性。

我應該使用 Label3D、TextMesh 還是投影控制?

在大多數情況下,建議使用 Label3D,因為它更易於設定並提供更高的渲染品質(特別是在禁用 3D 抗鋸齒功能的情況下)。

對於進階用例,TextMesh 更加靈活,因為它允許使用自訂著色器來設定文字樣式。自訂著色器允許修改最終的幾何形狀,例如沿著表面彎曲文字。由於文字是實際的 3D 幾何體,因此文字可以選擇具有深度,並且還可以有助於全局照明。

如果您需要 BBCode 或 Control 主題支援等功能,那麼使用投影的 RichTextLabel 節點是唯一的方法。