指南:攝像機光照材質(zhì)與性能優(yōu)化)
簡介圍繞Unity3D分屏式3D立體效果制作的RAR壓縮包面向Unity開發(fā)者、VR/AR應(yīng)用設(shè)計者以及希望在游戲或模擬項目中還原人眼雙目視差的工程師資源聚焦分屏渲染與立體投影兩條主線從左右眼相機配置、畫面分割到3D投影轉(zhuǎn)換均有涉及。內(nèi)容以相機系統(tǒng)為核心覆蓋平級雙相機的創(chuàng)建與位置偏移模擬約65mm瞳距、視錐體同步調(diào)整、屏幕左右分區(qū)渲染、行列交錯或紅藍(lán)等3D輸出格式適配以及后期色彩校正與深度增強還提及Unity Stereo Rendering Pipeline等高級渲染路徑對立體渲染性能與畫質(zhì)的優(yōu)化作用。包體為RAR壓縮格式共包含24個文件大小僅6.63MB文件構(gòu)成以8個動態(tài)鏈接庫DLL、4個配置文件、可執(zhí)行程序及Unity默認(rèn)資源為主另有少量輔助文檔與著色器資源可作為分屏立體效果的可運行示例或二次開發(fā)模板。已有1614人學(xué)習(xí)下載通過壓縮包可直觀體驗雙屏/并排式立體輸出也可參照其中相機參數(shù)與渲染設(shè)置快速復(fù)現(xiàn)分屏3D效果減少從零調(diào)試的彎路。1. unity3d立體效果不等于堆模型先把“立體感”拆成四個可調(diào)變量“unity3d立體效果”這個標(biāo)題落到干活層面就是一句話怎么把一個三維場景調(diào)出讓人信服的體積感、縱深感還要保證幀數(shù)撐得住。很多新手把模型拖進 Hierarchy、再打一盞平行光就以為畫面“立體”了實際跑起來才發(fā)現(xiàn)白模發(fā)灰、陰影死黑、材質(zhì)像塑料跟官網(wǎng) Demo 差了十萬八千里。這篇筆記寫給要做產(chǎn)品展示、數(shù)字孿生、工業(yè)仿真預(yù)覽的一線開發(fā)把攝像機、光照、材質(zhì)、模型導(dǎo)入和性能調(diào)優(yōu)串成一條能復(fù)現(xiàn)的鏈路。適合兩類人剛接觸 Unity、想搞明白立體感從哪來的新手以及被立體效果反復(fù)折磨的老手想知道到底是哪個參數(shù)在拖后腿。2. 先立骨架用攝像機與光照把場景推出縱深2.1 攝像機不對別的全是白搭FOV、物理曝光與視角高度立體感的第一層不是模型面數(shù)而是“眼睛”怎么看待這個場景。Unity 攝像機默認(rèn)的 Field of View 是 60°這個值本身沒有對錯但如果你做的是第一人稱漫游和產(chǎn)品展示建議先把它拉到 55° 到 70° 這個區(qū)間。FOV 調(diào)得太大畫面會像魚眼鏡頭中間物體被拉遠(yuǎn)邊緣直線全部彎曲縱深感被徹底破壞FOV 調(diào)得太小畫面又像長焦監(jiān)控前后物體被“壓”在一個平面上立體感直接被壓縮沒了。第二個容易被忽略的是 Physical Camera物理攝像機。URP 和 HDRP 里勾上 Physical Camera 后攝像機開始模擬真實鏡頭的 ISO、快門速度和光圈 F-Stop。不少人在默認(rèn)設(shè)置下調(diào)了一下午燈光切到物理攝像機模式畫面瞬間過曝或欠曝于是干脆放棄物理相機繼續(xù)用默認(rèn)的“虛擬鏡頭”。我一般會建議項目從第一天就打開 Physical Camera因為你最終要面對的環(huán)境千差萬別白天室外、室內(nèi)展廳、夜間屏顯都需要曝光邏輯而不是靠瞎猜亮度值硬調(diào)。視角高度也很影響立體感。人眼在地面上方約 1.6 米做室內(nèi)漫游和展館預(yù)覽時把攝像機放在這個高度畫面里的墻面傾斜角度、桌角透視才符合人的日常經(jīng)驗。相機放得太低地面占據(jù)了半個屏幕空間被壓縮放得太高又變成了俯瞰的“上帝視角”體積感雖在但代入感全無。下面這個腳本是我在數(shù)字孿生項目里常用的攝像機輔助工具讓玩家用滾輪平滑調(diào)節(jié) FOV展會現(xiàn)場可以隨時微調(diào)視角而不需要重啟程序using UnityEngine; public class CameraZoomFov : MonoBehaviour { [SerializeField] private Camera _cam; [SerializeField] private float _minFov 30f; [SerializeField] private float _maxFov 70f; [SerializeField] private float _smoothSpeed 8f; private float _targetFov; private void Awake() { if (_cam null) _cam Camera.main; _targetFov _cam.fieldOfView; } private void Update() { float scroll Input.GetAxis(Mouse ScrollWheel); if (Mathf.Abs(scroll) 0.001f) { _targetFov - scroll * 10f; _targetFov Mathf.Clamp(_targetFov, _minFov, _maxFov); } _cam.fieldOfView Mathf.Lerp(_cam.fieldOfView, _targetFov, Time.deltaTime * _smoothSpeed); } }腳本邏輯不復(fù)雜滾輪向上滑動放大視角向下滑動縮小視角目標(biāo) FOV 被 Clamp 在 30° 到 70° 之間再用 Lerp 做平滑過渡避免視角數(shù)值突變帶來的眩暈感。三個成員變量里_minFov 和 _maxFov 是上下邊界主要用來防止用戶把視角拖成明顯的畸變_smoothSpeed 是插值速度8 左右手感比較跟手如果希望鏡頭反應(yīng)更干脆可以調(diào)到 12但太高會顯得機械。這個腳本在觸摸屏設(shè)備上同樣適用只需要把滾輪輸入換成雙指捏合的距離增量。2.2 布光不是一盞燈就完事主光、補光與陰影參數(shù)場景里只有一盞默認(rèn)平行光畫面幾乎是必然發(fā)“平”的。立體感的本質(zhì)其實是亮度梯度一個物體頂面亮、側(cè)面暗、底邊帶一點點環(huán)境反射大腦才能判斷它的幾何轉(zhuǎn)折。一盞燈只能提供一個方向的高光環(huán)境光又把所有暗部均勻抬亮輪廓自然就糊了。布光這件事一半像物理一半像玄學(xué)但至少有一個可以復(fù)用的三層結(jié)構(gòu)。主光Key Light用平行光Directional Light決定整個畫面的陰影方向。角度上我習(xí)慣把它放在 30° 到 60° 的俯角之間這個區(qū)間陰影在物體下方拖出合適的長度既能體現(xiàn)體積又不會遮擋太多細(xì)節(jié)。補光Fill Light一般用點光源或區(qū)域光放在相機同側(cè)亮度控制在主光的 20% 到 40%它的存在只是讓正對相機的暗部不至於死黑而不是重新照亮全場景。輪廓光Rim Light放在被攝物體的背面亮度不需要高但能讓物體邊緣多一條亮邊把前景和后景“撕”開這是讓立體感立刻提升的常用手段。下表是我自己常用的燈光參考配置適合一般的產(chǎn)品展示和室內(nèi)場景顏色和強度還需要根據(jù)項目的天空盒微調(diào)燈光角色光源類型參考位置參考強度陰影設(shè)置主光Directional Light俯角 30°–60°面向主體0.8–1.2Soft Shadows補光Point Light相機側(cè)前方稍高于相機0.2–0.4關(guān)閉陰影輪廓光Point Light 或 Spot Light主體背后面向相機0.3–0.5關(guān)閉陰影環(huán)境光Lighting 窗口 Environment用 Skybox避免純色均勻填充取決于天空盒曝光不適用補光和輪廓光的陰影一般建議關(guān)掉否則陰影交叉會制造出很臟的雜色塊。主光的 Shadow Distance 也要注意URP 里默認(rèn)只有 10 米意味著 10 米外的物體全部沒有陰影遠(yuǎn)處物件懸浮在畫面上立體感瞬間崩塌。我一般會把它調(diào)到 50 米到 100 米具體看場景規(guī)模但這個值越大陰影貼圖占用越高需要跟性能做平衡。2.3 室內(nèi)與夜晚為什么總是一團黑自動曝光和反射探針把白天室外的光照參數(shù)原封不動搬到室內(nèi)畫面十有八九會黑成一片。很多人以為是燈光強度不夠把平行光從 1 拉到 3結(jié)果畫面反而過曝這就是沒搞懂自動曝光的邏輯。Unity 里如果開啟了 Adaptive Exposure自適應(yīng)曝光相機會統(tǒng)計畫面平均亮度并強行拉回中性灰室內(nèi)大部分墻面是暗色時系統(tǒng)會拼命提亮窗外的亮部就會白成一片反過來畫面里亮色太多系統(tǒng)又會壓低曝光暗部直接死黑。這個自動調(diào)節(jié)在室內(nèi)外混合的場景里是最難控制的效果也最像“呼吸感”——畫面亮暗忽閃忽閃。解法很直接在 Volume 面板里找到 Exposure把 Mode 從 Automatic 改成 Fixed然后手動給 EV 值。參考范圍上白天室外場景 EV 一般在 10 到 13室內(nèi)燈光展廳在 6 到 9夜晚場景可能跌到 3 到 5。固定曝光后整個場景的明暗關(guān)系完全由燈光決定調(diào)完燈效所見即所得雖然少了自動適應(yīng)但對展示類項目來說可控性遠(yuǎn)比自動調(diào)整重要。另一個讓室內(nèi)立體感打折的原因是反射探針缺失。很多金屬材質(zhì)和光滑瓷磚材質(zhì)在高光參數(shù)調(diào)高之后仍然顯得灰蒙蒙就是因為它們反射的是默認(rèn)的環(huán)境 Cubemap而不是周圍場景的真實色彩。在關(guān)鍵區(qū)域放上 Reflection Probe把 Type 設(shè)為 Baked然后在 Lighting 窗口觸發(fā)一次烘焙材質(zhì)表面就會出現(xiàn)墻面、地板和燈帶的反射關(guān)系。這一步不做材質(zhì)調(diào)得再細(xì)也像是貼了一張沒有光澤的紙。烘焙時反射探針的分辨率也不需要拉滿128 到 256 的 Cubemap 在多數(shù)室內(nèi)場景已經(jīng)足夠256 以上主要是鏡面要求很高時才考慮。提示固定曝光和反射探針這兩項是我檢查立體效果時最先排查的兩處。很多場景“發(fā)灰”“發(fā)悶”不是材質(zhì)不對而是曝光還在自動模式、場景里一個反射探針都沒放。3. 材質(zhì)與著色器立體感的“皮膚”怎么調(diào)才真實3.1 PBR 參數(shù)不能靠手感金屬度、光滑度與貼圖三件套模型是骨骼材質(zhì)是皮膚。Unity 里最常接觸的是 PBR 材質(zhì)URP 對應(yīng) Lit內(nèi)置管線對應(yīng) Standard。調(diào) PBR 參數(shù)時最容易出現(xiàn)的幻覺是“把 Smoothness 拉高就顯得高級”于是墻面被拉到 0.9最后看起來像一塊濕漉漉的塑料薄膜。非金屬墻面正確的光滑度一般在 0.2 到 0.4只有瓷磚、烤漆金屬、光滑石材才值得上 0.7 以上。Metallic 參數(shù)也一樣0 是純非金屬1 是純金屬金屬表面的反射會帶顏色傾向非金屬的反射則是白色且低強度的。把這兩個值當(dāng)成“好看程度”來調(diào)是材質(zhì)變假的主要根源。真正在立體感上起決定性作用的反而不是那幾個數(shù)值而是貼圖。純色材質(zhì)沒有微表面細(xì)節(jié)光照上去是完美光滑的數(shù)學(xué)曲面所以看起來“假”。我建議產(chǎn)品展示項目至少給每個主要材質(zhì)準(zhǔn)備三張貼圖Base Color基礎(chǔ)色、Normal Map法線貼圖和 Ambient Occlusion環(huán)境光遮蔽。法線貼圖負(fù)責(zé)在平面上制造磚縫、拉絲紋理和輕微凹凸AO 貼圖則給轉(zhuǎn)角、接縫和凹陷區(qū)域預(yù)埋陰影讓光線照過去時凹處自然比凸處暗。一張合適的 AO 貼圖能給整個場景的立體感提升一個檔次而且?guī)缀醪幌倪\行時性能。下面這個表給出了幾類常見材質(zhì)的建議參數(shù)配合貼圖使用更容易接近真實效果材質(zhì)類型Base Color 參考MetallicSmoothness建議貼圖組合水泥墻面偏灰的中性色00.2–0.4Normal AO磨砂金屬帶微色相變化的灰0.8–1.00.3–0.5Normal AO烤漆金屬高飽和或深色0.90.7–0.85Normal AO 遮罩地面瓷磚淺色或花紋00.7–0.8Normal AO自發(fā)光屏幕暗色面板 發(fā)光區(qū)00.3Emission 貼圖3.2 URP 管線切換的兼容性為什么色彩會變、白模突然變粉用內(nèi)置管線BIRP做的好好的場景切到 URP 后出現(xiàn)粉紅色材質(zhì)這是最典型的管線翻車現(xiàn)場。原因其實簡單URP 只認(rèn)識自己那套 Lit/Simple Lit Shader舊項目里的 Standard、Legacy Diffuse 甚至自定義 Shader 不兼容Unity 會在導(dǎo)入時做一次自動替換但替換有漏網(wǎng)之魚比如粒子系統(tǒng)的默認(rèn)材質(zhì)、第三方素材帶的特效 Shader就會直接失效變成粉紫色。解決這個問題的前提是項目一開始就確定管線而不是中途切換。如果已經(jīng)在 URP 項目里遇到我一般用兩條腿走路一是打開 Project Settings找到 Graphics 里的可編程渲染管線設(shè)置確認(rèn)每個質(zhì)量等級都掛了 Universal Render Pipeline Asset二是在項目里搜索所有失效的材質(zhì)球把 Shader 手動改成 URP/Lit改完再逐一檢查 Alpha Clip 和 Double Side 是否和原來一致。經(jīng)常被漏掉的是模型導(dǎo)入時自動生成的材質(zhì)它們可能還掛在舊 Shader 上需要到 Model 導(dǎo)入面板里重新關(guān)聯(lián)。URP 下還有一個小坑同一張貼圖在標(biāo)準(zhǔn)和 URP 里的顏色空間表現(xiàn)不同。線性空間下如果貼圖沒有正確標(biāo)記 sRGB畫面會整體偏灰。遇到這種情況去 Player Settings 里確認(rèn) Color Space 是 Linear并檢查貼圖導(dǎo)入設(shè)置中 Texture Type 是 Default 時 SRGB 是否正確勾選。很多時候“顏色變了”不是調(diào)色問題而是貼圖的顏色空間標(biāo)簽不對。3.3 運行時高亮不實例化材質(zhì)MaterialPropertyBlock 的正確姿勢數(shù)字孿生和產(chǎn)品展示里經(jīng)常要在運行時讓某個設(shè)備高亮、變色或閃爍。新手最常見的錯誤是直接拿到 Renderer 的材質(zhì)調(diào)用_material.color Color.yellow結(jié)果其他使用同一材質(zhì)球的物體也跟著變黃。原因在于 Unity 的材質(zhì)分“共享材質(zhì)”和“實例材質(zhì)”直接改材質(zhì)屬性引擎會為了當(dāng)前物體復(fù)制一份材質(zhì)實例再修改實例看起來“別的物體也變了”是因為有些物體的 Renderer 共享的是同一個實例或者你加的代碼訪問到了共享材質(zhì)。用代碼給單個物體高亮的推薦做法是 MaterialPropertyBlock它的核心好處是不實例化材質(zhì)而是把參數(shù)作為覆蓋寫到渲染命令里。下面是一個最小實現(xiàn)using UnityEngine; [RequireComponent(typeof(Renderer))] public class HighlightController : MonoBehaviour { private Renderer _renderer; private MaterialPropertyBlock _propBlock; [SerializeField] private Color _highlightColor Color.yellow; [SerializeField] private string _colorProperty _BaseColor; private void Awake() { _renderer GetComponentRenderer(); _propBlock new MaterialPropertyBlock(); } public void SetHighlight(bool active) { _propBlock.Clear(); if (active) { _propBlock.SetColor(_colorProperty, _highlightColor); } _renderer.SetPropertyBlock(_propBlock); } }這段代碼的核心是SetPropertyBlock它不會生成新的材質(zhì)實例而是把高亮顏色作為覆蓋屬性傳給 GPU。腳本注釋里寫清楚傳入的 Shader 屬性名URP 的 Lit 默認(rèn)基礎(chǔ)色屬性是_BaseColor內(nèi)置管線的 Standard 則是_Color這個名稱不一致是排錯時最容易忽略的。另一個參數(shù)是高亮顏色如果項目使用線性顏色空間眼睛看到的高亮色會比設(shè)置值偏亮需要在 Color 字段里手動降低一點強度。MaterialPropertyBlock 也有限制它不能覆蓋所有需要重構(gòu)關(guān)鍵字的材質(zhì)開關(guān)例如想從 Opaque 切到 Cutout或者切換 Shader就要走材質(zhì)實例。所以我的習(xí)慣是臨時狀態(tài)下標(biāo)優(yōu)先用 PropertyBlock長期狀態(tài)切換才考慮實例化材質(zhì)。4. 把 SolidWorks 模型導(dǎo)入 Unity 做成立體素材FBX 鏈路、單位與裝配體重建4.1 格式選擇為什么是 FBX 而不是 STL以及 SolidWorks 導(dǎo)出設(shè)置做工業(yè)設(shè)備展示和數(shù)字孿生手里拿到的十有八九是機械工程師給的 SolidWorks 模型。直接把 SLDPRT 或 SLDASM 拖進 Unity 是不可能的必須先在 SolidWorks 里導(dǎo)出通用格式。不少人圖省事導(dǎo)出 STL拖進來后發(fā)現(xiàn)模型是一個“實心石膏像”——沒有裝配體層級沒有零件名稱材質(zhì)全部丟失連顏色都看不見。STL 本質(zhì)上是三角網(wǎng)格描述格式只記錄表面幾何適合 3D 打印不適合實時渲染。正確做法是導(dǎo)出 FBX。FBX 能保留裝配體結(jié)構(gòu)、零件命名、材質(zhì)引用和簡單的顏色信息后續(xù)在 Unity 里還能按零件名做高亮和動畫。SolidWorks 里操作路徑是“文件 → 另存為 → FBX”導(dǎo)出選項里建議選擇“實體”而不是“曲面”因為 Unity 里實體網(wǎng)格更穩(wěn)定曲面容易產(chǎn)生雙面渲染問題。如果 SolidWorks 插件的版本允許導(dǎo)出前還要檢查“按實體導(dǎo)出”和“坐標(biāo)系單位”兩個選項坐標(biāo)系設(shè)置直接決定模型進入 Unity 后的朝向。4.2 導(dǎo)入面板四件套Scale Factor、軸轉(zhuǎn)換、材質(zhì)搜索和網(wǎng)格壓縮FBX 導(dǎo)入 Unity 后第一個翻車點一定是尺寸。SolidWorks 默認(rèn)單位是毫米Unity 空間單位是米直接按默認(rèn)設(shè)置導(dǎo)入一臺 2 米高的設(shè)備會變成 2000 米高的巨物攝像機在模型里穿行畫面全是灰色的內(nèi)部三角面。解決的入口在 Inspector 的 Model 頁簽把 Scale Factor 改成 0.01這相當(dāng)于把毫米換算成米。要注意這個 Scale Factor 有時會跟文件里的單位設(shè)置重復(fù)生效如果改完還是偏大再檢查 Model 頁簽里的 File Scale 和 Scene Units。第二件必須處理的事是坐標(biāo)軸。SolidWorks 的模型通常習(xí)慣 Z 軸向上Unity 是 Y 軸向上。如果導(dǎo)入后發(fā)現(xiàn)模型躺著可以在 Model 頁簽的 Conversion 里調(diào)整軸轉(zhuǎn)換Unity 一般會識別并自動轉(zhuǎn)換個別情況需要手動勾選 Bake Axis Conversion。第三個設(shè)置是 Material SearchFBX 導(dǎo)入時會試圖在項目里找到同名材質(zhì)我一般把 Search Location 設(shè)為 Recursive Up并確保貼圖目錄跟模型目錄在同一個資源文件夾下否則材質(zhì)會丟失變成灰模。網(wǎng)格壓縮則看項目需求。移動端和 WebGL 項目建議打開 Mesh Compression設(shè)置為 High能明顯減小包體但做工業(yè)展示時需要細(xì)節(jié)壓縮過高會造成法線變形、倒角變尖因此 PC 端展示我一般設(shè)成 Medium并配合后面要講的 LOD 做性能兜底。這些參數(shù)設(shè)置完畢后點擊 Apply不出意外你就得到了一個正立、等比例、帶零件層級結(jié)構(gòu)的產(chǎn)品模型。4.3 裝配體進來后亂成一團用編輯器腳本統(tǒng)一層級與樞軸即使模型正了、尺寸對了還有一個很常見的痛SolidWorks 導(dǎo)出的裝配體帶了好幾層空節(jié)點零件原點散落在世界各個角落想整體平移模型時發(fā)現(xiàn)只能挪動根節(jié)點想給某個零件做旋轉(zhuǎn)動畫時樞軸又不在零件中心。處理這種模型我一般不在場景里手拖而是寫一個編輯器腳本把根節(jié)點下的所有變換統(tǒng)一到世界原點下方并把每個零件的樞軸歸一到包圍盒中心。下面是一個簡化的 Editor 工具腳本放在 Assets/Editor 文件夾下即可效果是選中一個模型根節(jié)點后一鍵將所有子物體做“攤平”處理方便后續(xù)按零件操作using UnityEngine; using UnityEditor; public class CadHierarchyFixer : EditorWindow { [MenuItem(Tools/CAD Hierarchy Fixer)] public static void OpenWindow() { GetWindowCadHierarchyFixer(CAD Fixer); } private void OnGUI() { if (GUILayout.Button(Rebase Selected Root)) { if (Selection.activeGameObject ! null) { Rebase(Selection.activeGameObject.transform); } } } private void Rebase(Transform root) { Vector3 worldCenter GetWorldCenter(root); foreach (Transform child in root) { child.SetParent(null); child.position - worldCenter; child.SetParent(root, true); } root.position Vector3.zero; } private Vector3 GetWorldCenter(Transform root) { Bounds bounds new Bounds(root.position, Vector3.zero); foreach (MeshRenderer renderer in root.GetComponentsInChildrenMeshRenderer()) { bounds.Encapsulate(renderer.bounds); } return bounds.center; } }這段腳本的用途是把裝配體整體的包圍盒中心算出來再把所有子物體平移到以世界原點為中心的坐標(biāo)系里。參數(shù)上Rebase 函數(shù)里的SetParent(null)是臨時解除父子關(guān)系確保子物體平移時不會受到根節(jié)點位置的影響SetParent(root, true)的第二個參數(shù) true 表示保持世界位置再重新掛回根節(jié)點。腳本執(zhí)行后根節(jié)點歸零零件的世界坐標(biāo)不再有奇怪的大偏移后面對齊到地面、旋轉(zhuǎn)動畫都會方便很多。注意這個工具會改變場景里物體的位置操作前先保存一份場景備份畢竟這種批量操作沒有后悔藥。5. unity3d立體效果常見翻車現(xiàn)場法線、烘焙、LOD 三類問題一次講清5.1 邊緣發(fā)白、棱線閃爍法線與 UV 縫隙的鍋現(xiàn)象模型在場景里轉(zhuǎn)動時棱線邊緣一閃一閃地出現(xiàn)白色細(xì)線尤其在背光面更明顯像給模型描了一圈白邊。原因兩種情況最常見。一是模型在導(dǎo)出時硬邊和軟邊沒有設(shè)置正確的 Smoothing GroupsUnity 在頂點上做法線平均導(dǎo)致光照在邊緣處產(chǎn)生錯誤的過渡出現(xiàn)高光斷裂二是 UV 貼圖在接縫處沒有預(yù)留邊界相鄰兩片 UV 之間實際像素采樣到了相鄰區(qū)域于是邊緣摻雜了全白色或其他貼圖顏色。解決先回建模軟件里檢查 Smoothing Group硬邊比如立方體棱角必須單獨分一組平面過渡區(qū)域再分一組重新導(dǎo)出 FBX 后再看。像我們通常處理的 CAD 模型機械零件大多都是硬邊倒角在 Blender 或 3ds Max 里做一次“Clear Custom Split Normals Data”再重新計算法線也能解決大部分閃爍。如果白色來自 UV 接縫則需要在貼圖邊緣做 2 到 4 像素的 padding或者把 UV 島嶼之間拉開間隔。5.2 烘焙后有漏光和黑斑Lightmap 分辨率與 UV 重疊現(xiàn)象Lighting 面板點完 Bake場景里墻角出現(xiàn)一條異常的亮線或者暗部出現(xiàn)黑色的“雷影”斑塊。原因烘焙光照貼圖時參與烘焙的網(wǎng)格依賴第二套 UV。如果模型沒有第二套 UVUnity 會自動生成但自動展開經(jīng)常把兩個距離很遠(yuǎn)的三角形放到同一塊光照紋素里于是亮部和暗部互相污染墻角處則是因為 Lightmap 分辨率不夠明暗過渡帶恰好落在幾個粗糙紋素上形成一條“光縫”。解決去 Model 頁簽勾選 Generate Lightmap UV并把 Pack Margin 調(diào)到 4 以上讓 UV 島嶼之間留出更多空白。如果黑斑依然存在把 Lightmap Resolution 從默認(rèn)的 20 texels per unit 提高到 40 或 60再重新烘焙。注意提高分辨率會線性增加烘焙時間和運行時顯存占用項目初期先用 30 左右跑通整體效果最后再局部調(diào)高。5.3 模型一多就掉幀LOD、遮擋剔除和網(wǎng)格簡化怎么配合現(xiàn)象場景里放了上百臺設(shè)備模型后幀數(shù)從 60 掉到 20轉(zhuǎn)動視角時卡頓尤其明顯。原因每個高模零件都滿精度渲染GPU 的頂點處理壓力極大頻繁的 Draw Call 更是雪上加霜。很多從 CAD 來的高模單個零件動輒幾十萬三角面整個裝配體幾百個零件性能不崩才怪。解決優(yōu)先給大件模型掛 LOD Group三個階段分別為全精度0% 到 40% 屏幕占比、半精度40% 到 10%、低精度10% 以下。半精度和低精度模型不需要重新建模直接在 Unity 里使用 Mesh Simplifier 或?qū)霑r降低 Mesh Compression 配合腳本生成簡化網(wǎng)格并不追求視覺百分百一致只要距離遠(yuǎn)了看不出來就行。第二招是打開 Occlusion Culling在需要烘焙遮擋數(shù)據(jù)的區(qū)域放置 Occlusion Area讓相機看不到的物體直接跳過渲染色。第三招是優(yōu)先推動態(tài)建筑和產(chǎn)品展示項目使用 GPU Instancing相同零件的材質(zhì)球必須共享Static Batching 也在 Project Settings 里打開。這三招配合以后半百臺設(shè)備的場景通常能從 20 幀拉回到穩(wěn)定 60 幀。5.4 動態(tài)物體在烘焙場景里沒有正確陰影Mixed Lighting 與 Shadowmask現(xiàn)象場景已經(jīng)烘焙了光照貼圖但運行后一輛動態(tài)的小車在地面上沒有任何陰影看起來像懸浮一樣。原因靜態(tài)場景的光照貼圖只烘焙了靜態(tài)物體的明暗關(guān)系動態(tài)物體默認(rèn)依靠實時光照產(chǎn)生陰影而如果項目把 Lighting Mode 設(shè)成了 Subtractive動態(tài)物體的陰影會被壓縮得幾乎看不見。解決在 Lighting 面板把 Light Mode 從 Subtractive 改為 Shadowmask并確保主光源的 Shadow Type 打開。Shadowmask 模式下遠(yuǎn)距離的靜態(tài)陰影來自烘焙貼圖近距離的動態(tài)陰影由實時陰影補充雖然會增加少量 GPU 開銷但動態(tài)物體和靜態(tài)場景的接觸感會立刻真實起來。這個設(shè)置要在烘焙前就確定改完模式后再點一次 Bake否則現(xiàn)場仍然會對不上。6. 進階用視頻流與序列幀讓立體場景真正“活”起來6.1 用 VideoPlayer 把視頻流變成動態(tài)材質(zhì)靜態(tài)場景做得再精細(xì)也只能證明“這個模型好看”真正讓用戶覺得“這個對象在運轉(zhuǎn)”的是動態(tài)內(nèi)容。常見做法是把視頻流貼到模型表面展廳大屏、設(shè)備面板、操作界面都用動態(tài)視頻作為材質(zhì)貼圖。Unity 里做這個不需要寫解碼器直接用 VideoPlayer 組件就能實現(xiàn)。操作上我一般先建一個 Quad 或直接用產(chǎn)品面板的子物體給它一套 UV 對位的材質(zhì)然后把 VideoPlayer 組件拖到同一個物體上把 Target Material Renderer 指向該物體的 MeshRendererTarget Material Property 填_BaseMapURP Lit 下的基礎(chǔ)色貼圖屬性名內(nèi)置管線是_MainTex。再把 Video Clip 賦給 VideoPlayer勾選 Play On Awake場景運行后視頻就會自動鋪到模型表面。如果是網(wǎng)絡(luò)視頻流則把 VideoPlayer 的 Source 設(shè)為 URL播放前先監(jiān)聽 prepareCompleted 事件避免畫面還沒準(zhǔn)備好就播放黑屏。編碼上盡量選 H.264 的 MP4兼容性最好H.265 在部分移動平臺和 WebGL 上硬解支持很差會出現(xiàn)有聲音沒畫面或者直接卡死的情況。帶透明通道的視頻建議用 VP8 編碼的 WebM 或者序列幀動畫單純的綠幕視頻在 URP 下?lián)赶裥枰~外做 Shader工程量會大不少。我最近常用的替代方案是序列幀動畫把一小段視頻抽成 32 到 64 幀 PNG 序列用代碼按幀率刷新材質(zhì)貼圖效果接近視頻流但包體和內(nèi)存更可控。這個做法尤其適合火焰、指示燈閃爍、水波等小面積動態(tài)效果。我一直保留一個習(xí)慣每次在 Scene 視圖里覺得效果不對先把攝像機擺到人眼高度、關(guān)掉自動曝光、刪掉多余的燈光再一張張檢查貼圖和 LOD 鏈。這套流程看起來慢其實是節(jié)省時間最多的辦法——很多“立體感不好”的場景根源都不在那一個參數(shù)上。希望幫到你。本文還有配套的精品資源點擊獲取