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.

3D 文字

前言

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

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

也參考

你可以透過 3D 標籤與文字範例專案 來實際看看 3D 文字的效果。

本頁**不**涵蓋如何在 3D 環境中顯示 GUI 場景。若需相關資訊,請參考 3D 中的 GUI 範例專案。

Label (標齊)

../../_images/label_3d.png

Label3D 的行為類似於 Label 節點,但是在 3D 空間中。與 Label 節點不同的是,Label3D 不會 繼承 GUI 主題屬性。不過,它的外觀仍可自訂,並且和 Control 節點一樣,使用相同的字型子資源(包含支援 MSDF 算繪)。

優點

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

  • Label3D 可以使用點陣字型與動態字型(無論是否啟用 MSDF 或 mipmaps)。與 TextMesh 相比,這讓 Label3D 在這方面更具彈性,特別適合算繪具有自相交輪廓或彩色字型(如表情符號)的情境。

也參考

請參閱 使用字型 以了解設定字型匯入的相關指引。

限制

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

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

更多資訊請參考 3D 算繪限制頁面中的 透明度排序 章節。

當從遠處觀看 Label3D 時,文字的算繪品質也可能下降。為了提升文字算繪品質,可以 啟用字型的 mipmaps將字型切換為使用 MSDF 算繪

下一步

../../_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 等處下載到的字形時出現算繪問題,請嘗試改為從作者的官方網站下載。

  • 要讓文字算繪有抗鋸齒效果,需啟用全場景抗鋸齒(如 MSAA、FXAA 或時間性抗鋸齒 TAA)。若未啟用抗鋸齒,文字會顯得顆粒感明顯,尤其在遠處時更為明顯。詳情請參見 3D 抗鋸齒

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

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

相關範例請參考 3D 路徑點 範例專案。

優點

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

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

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

限制

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

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

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

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

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

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

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