【Unity筆記】Unity Camera.cullingMask 使用指南:Layer 精準控制、XR 多視圖與性能提升

在這里插入圖片描述


Unity Camera.cullingMask 使用指南:Layer 精準控制、XR 多視圖與性能提升

關鍵詞:Unity、Camera、Culling Mask、Layer 控制、XR 渲染分離、UI 顯隱、性能優化


特別說明:
本文為近期項目所遇問題的總結,僅純文字記錄,截圖不便分享。見諒!


文章目錄

  • Unity Camera.cullingMask 使用指南:Layer 精準控制、XR 多視圖與性能提升
    • 業務故事:一場“UI 不該出現在眼鏡里”的現場事故
      • 一、故事起源:展廳演示的第一天
      • 二、事故現場:UI “失控”現身
      • 三、初步排查與手動修復
      • 四、團隊決策:封裝一鍵Layer控制工具
    • 技術實踐指南:Unity 相機 Culling Mask 控制
      • 1. 背景與動機
      • 2. Culling Mask 原理解析
        • 2.1 定義
        • 2.2 示例代碼
      • 3. 實現目標與功能設計
        • 3.1 設計要求
      • 4. 完整腳本實現
      • 5. 示例調用與調試方法
        • 5.1 示例代碼
        • 5.2 編輯器拓展建議
      • 6. 應用場景分析
        • 6.1 XR 項目中 UI 分離顯示
        • 6.2 開發調試隔離
        • 6.3 Portal 鏡頭或切換效果
      • 7. 擴展功能建議
        • 7.1 支持 LayerMask 類型參數
        • 7.2 添加排除層功能
      • 8. 總結與最佳實踐
      • 9. 參考資料


業務故事:一場“UI 不該出現在眼鏡里”的現場事故

“當你的UI界面在VR眼鏡里擋住了用戶視野,卻在PC上毫無問題時,你會怎么做?”

一、故事起源:展廳演示的第一天

展館模型真實還原,觀眾佩戴 VR 頭顯后,可漫游各個展區;同時,操作員在 PC 端可通過鼠標實時監控視角、觸發高亮或切屏指令。

為了滿足雙端顯示需求,我們配置了三臺相機:

  • PC 主相機:渲染環境、UI、調試信息;
  • VR 頭顯相機:只渲染環境與玩家視角;
  • UI 專用相機:渲染所有 Canvas 元素,包含菜單、指南、調試層。

二、事故現場:UI “失控”現身

內部測試環境一切正常:PC 端界面完整,VR 端只見清爽的展示,無多余遮擋。
客戶演示當天,他戴上頭顯,第一反應卻是:“這 UI 是怎么回事?我眼前都是菜單,根本看不到展品!”

現場:

  • VR 端 UI 堆疊、遮擋用戶視野;
  • 點擊操作失效(實際上點擊走的是 PC 相機);
  • 用戶無法退出 UI,只能取下頭顯。

我們一看,果然:VR 相機和 UI 相機都在渲染相同的 UI Layer,“打包”給了頭顯。

三、初步排查與手動修復

打開 Unity Inspector,發現:

XRCamera.cullingMask = Everything
UICamera.cullingMask = Everything

兩臺相機都在渲染所有 Layer。
于是,測試人員反復手動:

  1. 取消 XRCamera 的 UI Layer;
  2. 勾選 UICamera 的 UI Layer;
  3. 切場景、切模式,效果斷斷續續,易出錯;

手動操作效率低,且在頻繁切換場景時容易遺漏。

四、團隊決策:封裝一鍵Layer控制工具

為避免 “手動取消勾選” 的痛苦,我們決定封裝一個可復用一鍵切換的 Culling Mask 控制組件,滿足:

  • 只渲染指定 Layer
  • 恢復渲染所有 Layer
  • 回退到上一次狀態
  • 自動識別 Camera.main
  • 支持多 Layer 名稱輸入

一旦寫出工具,任何相機都可在 Inspector 或運行時,通過簡短代碼切換渲染范圍。


上述故事純屬虛構,下面開始正文。


技術實踐指南:Unity 相機 Culling Mask 控制

1. 背景與動機

在 Unity 項目開發中,尤其是涉及 多層級 UI 管理、XR/VR 分視圖渲染、動態視角切換與性能調試 時,我們經常需要靈活控制相機渲染對象的范圍。

本質上,我們希望控制:某個 Camera 渲染哪些 Layer

常見應用如:

  • XR 項目中:僅 PC 屏幕顯示 UI,VR 頭顯中不顯示;
  • Portal 或多視角切換場景:主相機與子視角相機渲染不同對象;
  • 開發調試模式:僅在 Debug 模式下顯示 Gizmo 層;
  • 鏡頭特效系統:僅渲染特定對象做后處理。

這些都離不開對 Unity 相機的 Culling Mask 的精細控制。

2. Culling Mask 原理解析

2.1 定義

Unity 中的每個 Camera 都有一個 Culling Mask 屬性,它是一個 32 位的位掩碼(bitmask),用于表示該相機應該 “看到” 哪些 Layer。

Camera.cullingMask: int → 每一位代表一個 Layer(最多支持 32 個)
2.2 示例代碼
// 只顯示 UI 層
camera.cullingMask = 1 << LayerMask.NameToLayer("UI");// 同時顯示多個層(使用按位或)
camera.cullingMask = (1 << Layer1) | (1 << Layer2);// 使用 LayerMask 工具方法
camera.cullingMask = LayerMask.GetMask("Default", "UI", "GuideLayer");

3. 實現目標與功能設計

我們封裝一個組件 CameraCullingMaskController,具備以下功能:

方法名功能描述
`ApplyLayersOnly("UIDefault")`僅顯示指定 Layer(多個以“”分隔)
RestoreEverything()恢復顯示所有 Layer(即 LayerMask.All)
RestoreOriginal()回退到上一次設置前的原始狀態
3.1 設計要求
  • 可自動識別并使用 Camera.main
  • 支持傳入多個 Layer 名;
  • Layer 合法性校驗與報錯提示;
  • 可擴展性好,便于嵌入 XR 項目。

4. 完整腳本實現

using UnityEngine;namespace XRCoreRuntime.Runtime.Component
{/// <summary>/// 控制 Camera 的 CullingMask 顯示特定 Layer 或恢復狀態/// </summary>public class CameraCullingMaskController : MonoBehaviour{[Header("指定相機,未指定則使用 Camera.main")]public Camera? mainCam;private int originalCullingMask;public void ApplyLayersOnly(string targetLayers){if (string.IsNullOrEmpty(targetLayers)) {Debug.LogWarning("傳入的 Layer 字符串為空!");return;}mainCam ??= Camera.main;if (mainCam == null) {Debug.LogWarning("Camera 未找到!");return;}originalCullingMask = mainCam.cullingMask;var names = targetLayers.Split('|');int mask = 0;foreach (var name in names){int layer = LayerMask.NameToLayer(name.Trim());if (layer == -1){Debug.LogError($"Layer \"{name}\" 不存在!");continue;}mask |= 1 << layer;}if (mask == 0){Debug.LogWarning("未能解析出有效 Layer!");return;}mainCam.cullingMask = mask;}public void RestoreEverything(){mainCam ??= Camera.main;if (mainCam != null)mainCam.cullingMask = ~0;}public void RestoreOriginal(){mainCam ??= Camera.main;if (mainCam != null)mainCam.cullingMask = originalCullingMask;}}
}

5. 示例調用與調試方法

5.1 示例代碼
var ctrl = GetComponent<CameraCullingMaskController>();// 顯示 UI 和 GuideLayer
ctrl.ApplyLayersOnly("UI|GuideLayer");// 恢復所有
ctrl.RestoreEverything();// 回退到原狀態
ctrl.RestoreOriginal();
5.2 編輯器拓展建議

可通過 CustomEditor 創建按鈕,直接點擊控制:

@startuml
actor Developer
participant InspectorButton
participant CameraCullingMaskControllerDeveloper -> InspectorButton : 點擊 "顯示 UI"
InspectorButton -> CameraCullingMaskController : ApplyLayersOnly("UI")Developer -> InspectorButton : 點擊 "恢復全部"
InspectorButton -> CameraCullingMaskController : RestoreEverything()
@enduml

6. 應用場景分析

6.1 XR 項目中 UI 分離顯示

場景:希望 UI 僅顯示在 PC 上,頭顯中不顯示。

做法

// VR 主相機只渲染環境與默認層
ctrl.ApplyLayersOnly("Environment|Default");
// UI 相機只渲染 UI
ctrl.ApplyLayersOnly("UI");
6.2 開發調試隔離

將調試工具放入 DebugLayer,僅調試時開啟:

ctrl.ApplyLayersOnly("Default|DebugLayer");
6.3 Portal 鏡頭或切換效果

用多臺 Camera 渲染不同視角,組合效果類似:

主相機:環境 + 玩家
鏡頭相機:僅渲染特效層

7. 擴展功能建議

7.1 支持 LayerMask 類型參數

ApplyLayersOnly(string) 改為 ApplyLayersOnly(LayerMask mask),便于在編輯器中使用 MaskField

7.2 添加排除層功能

增加方法:

public void ApplyExcludeLayers(string excludeLayers);

使用位操作方式:

mainCam.cullingMask = ~LayerMask.GetMask("Debug", "UI");

8. 總結與最佳實踐

本文從業務事故切入,結合實際項目需求,詳盡講解了 Unity 中相機 Culling Mask 的使用方法。通過封裝 CameraCullingMaskController,實現了:

  • 動態 Layer 渲染控制;
  • UI 顯示隔離;
  • XR 多視圖調度;
  • Portal 場景優化;
  • 性能剔除帶來的幀率提升。

技術的價值在于解決實際問題。
下次再遇到“UI 不該出現在眼鏡里”的煩惱時,試試這套工具,讓每個相機都“只看”自己應該看的內容。

9. 參考資料

  • Unity 官方文檔

    • Camera.cullingMask
    • LayerMask


從最初的“UI 失靈”到完整的 Culling Mask 控制方案,我們體會到:

一行代碼的變化,能讓整個系統更加健壯、可維護,也讓開發效率成倍提升。

希望這篇文章,既讓你在項目演示不再手忙腳亂,也為日后更復雜的多相機、多視圖場景打下堅實基礎。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/93211.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/93211.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/93211.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

攜帶參數的表單文件上傳 axios, SpringBoot

頁面上的表單如上圖, 點擊確定按鈕需要把參數統一傳給后端.前端代碼:表單的提交方法const submit async () > {const formData new FormData();formData.append("bookName", bookForm.value.bookName);formData.append("author", bookForm.value.auth…

黑馬JavaWeb【復習到哪更新到哪】

登錄認證&#xff08;復習Javaweb的登錄校驗&#xff09; 登錄功能 思路就是loginController->service層->mapper層&#xff0c;從數據庫中查找username和password是否和前端用戶提交的表單內容一致&#xff0c;一致就登錄成功&#xff0c;否則就返回登錄失敗的信息。 登…

NVMe高速傳輸之擺脫XDMA設計21:PCIe請求模塊設計(下)

在接收到請求總線接口的請求事務后&#xff0c;當請求類型的值為0時&#xff0c;表示通過PCIE硬核的配置管理接口發送請求&#xff0c;由于請求接口的接口和時序與配置管理接口基本一致&#xff0c;因此此時直接將請求接口信號驅動到配置管理接口完成請求的發送&#xff0c;請求…

機器學習sklearn:不純度與決策樹構建

不純度與決策樹構建不純度概念&#xff1a;決策樹通過不純度指標來選擇最佳分割節點和分枝方式不純度衡量節點中樣本類別的混雜程度不純度越低&#xff0c;節點中樣本類別越純凈&#xff0c;擬合效果越好常用不純度指標&#xff1a;信息熵(Entropy)&#xff1a;基于信息論的概念…

rk356x IR紅外發射與接收之NEC協議

紅外接收紅外接收頭解碼器&#xff08;紅外信號解碼&#xff0c;主要是NEC解碼&#xff09;紅外發射器紅外發光二極管晶振NEC編碼組成共32位&#xff08;4bit&#xff09;&#xff1a;由8位用戶碼1 8位用戶碼2 8位命令碼 8位命令碼反碼有時會存在按鍵一直按下的一幀信息&…

C++算法之單調棧

C算法中的單調棧&#xff1a;從入門到實戰指南 大家好&#xff01;今天我們來聊聊C算法中一個超級實用的工具——單調棧。別被名字嚇到&#xff0c;它其實很簡單&#xff0c;就像排隊買奶茶一樣&#xff1a;隊伍總是從矮到高&#xff08;或從高到矮&#xff09;排得整整齊齊&a…

React入門指南——指北指南(第二節)

React 實踐:創建你的第一個待辦事項列表 在前面的章節中,我們學習了 React 的核心概念(組件、Props、State 等)。本節將通過一個實際案例——創建待辦事項列表(Todo List),幫助你鞏固這些概念,并掌握 React 中處理用戶交互、動態數據的基本方法。 案例目標 我們將構…

WAIC看點:可交付AI登場,場景智能、專屬知識將兌現下一代AI價值

7月28日&#xff0c;為期三天的2025世界人工智能大會&#xff08;WAIC 2025&#xff09;在上海落下帷幕。作為全球 AI 領域最受關注的盛會之一&#xff0c;今年 WAIC 聚焦 AI 關鍵命題&#xff0c;圍繞大模型與智能體應用、算力新基建及大數據、智能終端與具身智能、AI金融、AI…

設計模式(十一)結構型:外觀模式詳解

設計模式&#xff08;十一&#xff09;結構型&#xff1a;外觀模式詳解外觀模式&#xff08;Facade Pattern&#xff09;是 GoF 23 種設計模式中的結構型模式之一&#xff0c;其核心價值在于為一個復雜的子系統提供一個統一、簡化的高層接口&#xff0c;從而降低客戶端與子系統…

接口測試核心概念與實踐指南

核心概念什么是接口&#xff1f;軟件不同部分之間進行通信和數據交換的約定或契約。定義了&#xff1a;請求方 (Client/Consumer) 如何調用&#xff08;方法、URL、參數&#xff09;。提供方 (Server/Provider) 如何響應&#xff08;數據結構、狀態碼&#xff09;。雙方需要遵循…

【NLP輿情分析】基于python微博輿情分析可視化系統(flask+pandas+echarts) 視頻教程 - 熱詞數量分析日期統計功能實現

大家好&#xff0c;我是java1234_小鋒老師&#xff0c;最近寫了一套【NLP輿情分析】基于python微博輿情分析可視化系統(flaskpandasecharts)視頻教程&#xff0c;持續更新中&#xff0c;計劃月底更新完&#xff0c;感謝支持。今天講解熱詞數量分析日期統計功能實現 視頻在線地…

ICPC 2024 網絡賽(I)

M. Find the Easiest Problem 題目大意 給定所有的提交記錄&#xff0c;找到通過隊伍最多且字典序最小的題目。 解題思路 按題意模擬即可 代碼實現 #include <bits/stdc.h>using i64 long long;int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std…

【快捷指令】ios/macos快捷指令如何調用api接口(json請求例子)

一、步驟 之前已經寫了一個【n8n】使用 n8n 創建插入數據到mysql的api&#xff08;圖解步驟&#xff09;博客,感興趣的可以看一下. 流程&#xff1a; 快捷指令調用api—開源工作流n8n上設置個快速寫數據庫的工作流 這樣就實現了記錄體重的一個快捷指令 二、步驟說明 1、…

「源力覺醒 創作者計劃」_文心大模型4.5系列開源模型,意味著什么?對開發者、對行業生態有何影響?

前言&#xff1a;哈嘍&#xff0c;大家好&#xff0c;今天給大家分享一篇文章&#xff01;并提供具體代碼幫助大家深入理解&#xff0c;徹底掌握&#xff01;創作不易&#xff0c;如果能幫助到大家或者給大家一些靈感和啟發&#xff0c;歡迎收藏關注哦 &#x1f495; 目錄「源力…

CanMV-K230 AI學習筆記系列

在學習了一段時間CanMV-K230后&#xff0c;感覺雖然可以直接調用復雜的模型&#xff0c;但是很多環節不是很明白&#xff0c;因此希望能夠從基礎的模型開始逐漸深入學習。 下面為已經完成的一些筆記及計劃&#xff1a; 1 CanMV K230使用經驗分享 這個是剛開始學習K230時&#…

EtherCAT IGH別名(Alias)

EtherCAT 中的 Alias 是一個 16 位的數值&#xff0c;用于在拓撲結構中唯一標識從站&#xff08;除 Position 外的輔助定位方式&#xff09;IGH查看別名 “0:0”, 第一個0是別名(alias)&#xff0c;后面是位置(position) sudo ethercat slave -p 0 0 0:0 PREOP SV660_1Axi…

墨者:通過sqlmap解決SQL手工注入漏洞測試(PostgreSQL數據庫)

使用Kali Linux中的sqlmap工具進行PostgreSQL手工注入漏洞測試實戰 前言 SQL注入是Web安全中最常見的漏洞之一。本文將演示如何使用Kali Linux中的sqlmap工具對PostgreSQL數據庫進行手工注入測試&#xff0c;通過實戰案例幫助安全研究人員更好地理解漏洞原理和測試方法。 測…

Linux筆記5——常用命令-4

幫助命令man 命令&#xff08;查看命令的幫助&#xff09;注&#xff1a;C7版本中有中文解釋例&#xff1a;man lsman -f 命令 #查看命令有哪些級別的幫助&#xff0c;使用前要執行mandb生成man緩存信息&#xff0c;否則命令執行不成功man級別1.查看命令的幫助3.查看函數…

優化Linux高并發:文件描述符與端口范圍的協同調優

既然已經通過調整nofile&#xff08;最大文件描述符數量&#xff09;來支持高并發&#xff0c;為什么還需要調整net.ipv4.ip_local_port_range&#xff08;本地端口范圍&#xff09;&#xff1f;這兩個參數看似都與高并發有關&#xff0c;但它們的作用和影響范圍不同。 1. 文件…

.NET-鍵控服務依賴注入

有時候我們在服務注冊的時候會遇到這樣一個場景&#xff0c;我們的同一個接口&#xff0c;有著多個實現&#xff0c;且我們還要同時使用這些實現的時候&#xff0c;這個時候該怎么辦&#xff1f;我們可以使用鍵控服務依賴注入 鍵控服務依賴注入&#xff08;Keyed Dependency In…