透過 Unity 創造手機遊戲光照

光照是遊戲最重要的面向之一,可以營造氛圍、引導玩家、找出威脅或目標等。光照可以建立或破壞遊戲的視覺畫面。舉例來說,良好的光照可能會讓不好的模型在遊戲中呈現更佳,而光照不佳則可能會導致模型看起來更糟。

本指南提供在手機遊戲中改善光照效能的相關資訊。決定使用光照的方式會影響手機遊戲的效能。有效運用光照十分重要,以確保遊戲可以盡可能地順暢執行。

本文部分內容以 Arm Limited 的著作為基礎,並受版權保護。

轉譯管道選項

Unity 的舊版轉譯管道包含下列轉譯路徑:

  • 前向轉譯
  • 延遲陰影

前向轉譯

有了前向轉譯,採用即時光源代價非常高昂。如果減少每一像素顯示的光源數量,就可以抵銷這個代價。

延遲陰影

延遲陰影需要 GPU 支援。在相容的硬體上,延遲陰影可以透過極高的光源擬真度轉譯大量的即時光源。可惜的是,由於延遲陰影在行動裝置 GPU 上頻寬較低,因此效能不佳。

製作行動標題時,請務必盡可能讓多部裝置順暢地執行遊戲。

Universal Render Pipeline

Unity 已開發 Universal Render Pipeline (URP)。我們強烈建議您在手機遊戲中使用 URP。

光源模式

系統會根據光源的移動情形或在場景中的使用情況,使用不同的光源模式。 光源模式類型有不同的效能特性。實作光源時,請考量以下幾點:

  • 針對靜態光源使用「baked」(烘焙)。最適用於在執行階段未變更光源的物體。烘焙光源是指在稱為「光照貼圖」的紋理貼圖上,預先計算並儲存光源資料的過程。
    • 無法在執行階段修改烘焙光源。光照貼圖中的光源和陰影是靜態的。由於所有光照作業都在 Unity 中經過預先處理,因此沒有任何執行階段的光源計算會影響效能。
    • 動態陰影無法用烘焙光源來建立。動態或移動中的物體可能會看起來很奇怪。
  • 針對您打算與移動中物體互動的固定光源,使用「mixed」(混合) 光源。 舉例來說,玩家移動時火炬會投射光源在玩家身上並產生陰影。
    • 混合光源可以產生動態的直接光源和陰影。
    • 您可以為靜態物體的光照貼圖計算中加入混合光源。
    • 您可以在執行階段變更光源強度。系統只會更新直接光源。
    • 昂貴。
  • 針對動態或可移動的光源使用「real time」(即時) 光源,例如從地面升起並爆炸的火球所投射的光源。
    • 您可以在執行階段修改動態光源和陰影屬性。
    • 即時光源無法烘焙為光照貼圖。
    • 極為昂貴。

詳情請參閱 Unity's Lighting Pipeline (Unity 的光照管道)。

盡可能使用靜態光源,避免使用動態光源

系統會在每個影格計算並更新「動態」或「即時」的光源。這種做法很適合用於移動中的物體、互動及營造氣氛。

相反地,靜態光源資訊則會烘焙為光照貼圖。光照貼圖用量可以讓物體免於每一頂點像素或每一像素高昂的光源運算。光照貼圖紋理的轉譯成本一律比動態光源的還來得低。我們建議將手機遊戲實作烘焙光源做為第一首選。

光照貼圖烘焙

預先計算出的光源效果稱為「光照貼圖烘焙」。光源的效果會儲存在另一個名為「光照貼圖」的紋理中。光照貼圖可用於加強物體外觀。只需對場景的每個疊代進行一次光照烘焙即可。如果變更場景的幾何圖形或變更烘焙光源的參數,則需要重新烘焙光照貼圖。除了光照貼圖紋理的費用外,在執行階段不會產生任何額外的效能費用。這是最初在行動平台上創造光照的最佳方法。

烘焙光源不會受到場景任何動態或移動中的面向所影響。 烘焙光源確實包含所有靜態元素的烘焙全域照明。這表示光照貼圖的運算包含從其他靜態物體反彈的直接光源和直接照在物體上的烘焙光源。

圖 1. Armies 技術示範中使用的全烘焙光源設定。

如要烘焙光源,請執行以下三個步驟。

步驟 1:將光源設為「Mixed」或「Baked」

將光源的「Mode」(模式) 設為「Mixed」(混合) 或「Baked」(烘焙)。針對手機遊戲,最好使用「Baked」(烘焙) 而非 「Mixed」(混合) 光源。「Baked」(烘焙) 是轉譯光源所費較低的方法。

圖 2. Unity 中的「Mode」(模式) 設定。

步驟 2:將物體設為靜態

將任何受到烘焙光源影響的物體設為「Static」(靜態)。標示為靜態的物體有多種最佳化方式,但通常在「Static」(靜態) 下拉式清單中選取「Everything」(全部) 是最佳的做法。將物體標示為「Static」(靜態) 後,Unity 就會知道要將物體納入光照烘焙中。

圖 3. 靜態選單範例。

步驟 3:烘焙光源

可以透過「Window」(視窗) >「Rendering」(轉譯) >「Lighting Settings」(光照設定) 中的「Lighting」(光照) 選單來烘焙光源。

烘焙光源時,儲存的資料是根據您開始烘焙時使用中的場景。系統會產生與烘焙場景名稱相同的資料夾。這個資料夾會儲存所有光照資料的元件。如果專案一次載入多個場景,您必須為每個場景分別設定烘焙光源。如要調整場景,必須要重新烘焙光源。

圖 4. 烘焙光照貼圖範例。

將光照貼圖最佳化

將光源設定為烘焙後,請務必將烘焙貼圖最佳化。光照貼圖的大小會因烘焙時的設定而異。必須讓行動裝置維持較低的記憶體用量,因此光照貼圖必須受到監控。

在以下 Armies 示範的範例中,有七張 1024x1024 像素的光照貼圖。在貼圖預覽畫面中,可以看到光照貼圖上有網格。 選取的網格已醒目顯示。

圖 5. 這是光照貼圖的範例,藍色的部分是已選取的網格。

在「Lightmapping Settings」(光照貼圖設定) 中的多項設定和貼圖大小,決定了每張貼圖會使用多少記憶體和儲存空間。以下章節說明幾項重要的設定。

烘焙模式

Unity 提供以下三種在場景中烘焙光源的方法:

  • Enlighten:僅支援 2020 年為止的長期支援 (LTS) 版本。 請勿將這個方法用於新專案。
  • Progressive CPU (漸進式 CPU):此方法可漸進式建立光照貼圖,因此能節省大量時間。 如果選取「Prioritize View」(優先檢視畫面),系統會優先呈現「Scene」(場景) 檢視畫面中的區域。 如此一來可減少設定場景光源的疊代時間。
  • Progressive GPU (漸進式 GPU):運作方式與「Progressive CPU」相同,但在 GPU 而非 CPU 上產生光照貼圖。相較於使用 CPU,這種方法在支援的硬體上可大幅縮短烘焙時間。 設定「Progressive GPU」(漸進式 GPU) 還有其他需求條件。如要瞭解更多相關規定,請參閱「The Progressive GPU Lightmapper」(漸進式 GPU 烘焙模式) 頁面。

圖 6. 「Lightmapper Settings」(烘焙模式設定) 可讓您變更場景的烘焙方法。

紋素

「紋素」又稱為紋理,是紋理貼圖中的個別像素。紋素會為光源照射到物體的每個點,儲存光照貼圖中的光源資訊。每個單位空間使用的紋素越多,會影響光照的品質、烘焙的運算時間、磁碟儲存空間費用,以及光照貼圖的 VRAM 費用。

如要減少所需的光照貼圖資料量,請調整「Lightmapping Settings」(光照貼圖設定) 中烘焙的各單位紋素量。

圖 7. 光照貼圖可用的設定。

在「Lightmapping Settings」(光照貼圖設定) 中,「Lightmap Resolution」(光照貼圖解析度) 參數控制了光照貼圖中每單位使用的紋素量。以下是採用不同「Lightmap Resolution」(光照貼圖解析度) 設定的立方體範例。您可以看到較高的解析度如何快速地增加所需的工作量。

圖 8. 第一個立方體的「Lightmap Resolution」(光照貼圖解析度)1。第二個立方體的「Lightmap Resolution」(光照貼圖解析度)2。第三個立方體的「Lightmap Resolution」(光照貼圖解析度)5

如要查看紋素在場景中呈現的樣子,請選取「Scene」(場景) 檢視畫面中的「Draw Mode」(繪圖模式) 下拉式清單,然後選擇「Baked Lightmap」(已烘焙的光照貼圖)

已烘焙的物體會有棋盤格重疊於其上。棋盤模式會顯示烘焙光源時紋素的分布情形。

在以下範例中,將 Armies 示範的「Lightmap Resolution」(光照貼圖解析度)15 減少為 12,會使得所需的光照貼圖數量從七減少為四個。

圖 9. 「Lightmap Resolution」(光照貼圖解析度)12 的 Armies 示範。

紋素使用量

雖然您可以在整個場景中為每個單位設定紋素使用量,但有些物體往往不需要使用到這麼多紋素。

Unity 可讓您控制每個物體使用的紋素數量。在物體的「Inspector」(檢查器) >「Mesh Renderer」(網格轉譯器) 中,「Scale In Lightmap」(光照貼圖等級) 參數值可控制光照貼圖中物體所使用的紋素量。

在下列範例中,左邊的立方體在每個烘焙單位中有五個紋素的光源資訊。右側立方體的「Scale In Lightmap」(光照貼圖等級) 則設為 0.5。該項設定將光源的紋素等級調整為 2.5,如此一來在光照貼圖中就會比左側方塊所需的空間來得少。

圖 10. 光照貼圖解析度不同的兩個立方體。

圖 11. 您可以變更「Scale In Lightmap」(光照貼圖等級) 設定,讓物體擁有較少的紋素。

盡量避免在以下情況使用多個紋素:

  • 玩家看不到的介面和物體。這樣可以避免將記憶體耗費在螢幕上沒有顯現的細節。
  • 光源變化極少的表面,例如在陰影處的物體或由單一光源照射的物體。
  • 細小的物體。這些物體接收的光源量將無法為場景的最終轉譯帶來太多幫助。

盡可能減少人造光源

為了減少處理某些需求,您可以人造出某些元素。這麽做可以讓您的內容看起來有使用到光源,但實際上使用的是更有效率的方法。

人造陰影

使用即時陰影的費用高昂。這些陰影由稱之為「陰影貼圖」的技術所產生。將場景的幾何圖形轉譯至陰影貼圖的費用,與已啟用陰影繪製的頂點數量相稱。建議您限制投放陰影的幾何圖形數量,以及投射光源的即時陰影數量。

您可以在沒有動態光源的情況下為動態的物體創造人造陰影。這樣有助於降低轉譯成本,並能創造出與動態陰影相似的效果。以下是實作人造陰影的方法:

  • 使用 3D 網格 (例如置於人物下方的平面或四方場地),然後將模糊的紋理套用至該網格。
  • 對於更複雜的 blob 陰影,您可以自行撰寫自訂著色器

以下範例顯示使用 3D 網格來處理陰影的結果:

圖 12. Armies 技術示範中實作陰影的情形。

直接在紋素上繪製光源資訊

如果將部分陰影繪製成紋理,就會減少額外光源所需的運算。由於所需的光照貼圖資料較少,這麽做可以在烘焙場景光源時節省記憶體。

光照探針

在動態物體上使用已烘焙光源時,物體並不受光照貼圖的影響。這可能會使得物體看起來不像是場景的一部分。

您可以使用光照探針來解決這個問題。光照探針和光照貼圖的優點類似。這兩個功能皆會儲存可以先計算的光源資料,以供執行階段使用。這麼做可以節省大量的運算成本以編輯時間。

光照貼圖為某些表面將紋素中接收到的光源進行編碼時,光照探針會儲存通過空白處的光源。您可以將這項資料用於移動的光源物體。光照探針可協助在場景中將已烘焙物體與動態物體結合。

光照探針功能最適合用於場景中移動的光源物體。探針會運用烘焙光源讓移動中的物體和場景中的光源相同。比起即時光源,使用光照探針照亮動態物體的費用較低。

您可以在「Static Lighting with Light Probes」(使用光照探針的靜態光照) 和「Light Probes」(光照探針) 頁面瞭解更多資訊。

圖 13.在 Armies 技術示範中,放置於動態人群上的光照探針。

Mesh Renderer 設定

無論場景使用的光源類型為何,請務必確認「Mesh Renderer」(網格轉譯器) 的設定正確無誤。

關閉任何未使用的功能。即使物體並未受到光照,在轉譯場景時,「Cast Shadows」(投射陰影) 等設定仍會增加費用。以下「Mesh Renderer」(網格轉譯器) 的設定範例是針對圖 13 中顯示的人物。這個人物使用光照探測資料而非反射探測。

光照探測的「Blend Probes」(融合探測) 設定會將最接近光照探測的光源資訊與人物融合。人物在場景中移動時,光照探測所影響的人物會有所改變。由於轉譯使用 blob 方法,因此系統已關閉「Cast Shadows」(投射陰影)。「Receive Shadows」(接收陰影) 也已關閉,因為場景已經過烘焙,且沒有即時陰影。

圖 14.圖 13 轉譯的「Mesh Renderer」(網格轉譯器) 設定。

即時光源和光源類型

建議您使用烘焙光源光照探針和人造光源技術 (例如已繪製的光源紋理或著色器材質效果) 來處理光源。不過,如果需要即時光源,則必須考慮要使用的光源類型。

每種光源類型計算光照的費用都不同。以下清單詳細列出每種光源類型:

  • 定向光源:這類光源有統一方向且不會衰减。 定向光是最便宜的即時光源。每個場景通常只需要一道定向光。有了前向轉譯 (即行動裝置建議的轉譯路徑),如果場景中沒有定向光源,Unity 將採用預設的定向光源。
  • 聚光燈:聚光燈只會投射在錐體以內的範圍,而不會照射到錐體以外的物體。因此相較於球面點光源,這類聚光燈的運算成本較低。為充分發揮效能,請保持適當的錐體寬度,只將光源照射到欲投射的物體。
  • 點光源:這類光源會朝所有方向發射光源。朝各個方向投射光源很實用卻很昂貴。在廣闊區域使用點光源所費不貲。此外,陰影運算可能是光照中最昂貴的部分。如果朝所有方向投射光源,會產生更多陰影和也會需要更多運算。