
1. 项目概述为什么你的Static勾选可能是错的在Unity项目里尤其是那些场景稍微复杂点的3D项目性能优化是个绕不开的话题。很多开发者特别是刚接触Unity不久的朋友一听到“优化”两个字下意识就会打开场景里所有静态物体的Inspector面板把那个“Static”复选框挨个勾上。心里想着“勾上Static总没错吧能让引擎优化何乐而不为” 我以前也这么干过直到项目在移动设备上跑得跟幻灯片一样或者烘焙Occlusion Culling遮挡剔除时发现要么没效果要么烘焙时间长得离谱甚至烘焙数据异常庞大我才意识到问题没那么简单。这个“Static”复选框在Unity的语境下它不是一个单一的开关而是一个包含了多种优化系统如Batching、Navigation、Occlusion Culling、Reflection Probe等的“总开关”。我们今天要深挖的就是它对于Occlusion Culling这个核心渲染优化技术的影响。具体来说是Occluder Static和Occludee Static这两个子选项到底该怎么用。网络上的讨论很多官方文档的解释有时又显得过于简略导致很多开发者包括一些有经验的对这两个概念的理解都存在混淆。最常见的误区就是把所有静态物体都同时勾上Occluder和Occludee或者完全搞反了它们的角色最终导致遮挡剔除系统要么不工作要么产生错误的剔除结果画面出现“穿帮”物体在应该被看到时消失了。所以这篇文章的目的就是彻底讲清楚Occluder遮挡物和Occludee被遮挡物在Unity遮挡剔除系统中的定义、区别、以及最关键的——实战中的勾选策略。我会结合具体的场景案例告诉你什么样的物体应该只当Occluder什么样的应该只当Occludee什么样的可以身兼二职以及什么样的应该一个都不勾。理解这些不仅能让你正确使用遮挡剔除更能让你对Unity的静态批处理、动态批处理等其他优化手段有更深刻的认识避免因错误的Static设置引发一系列连锁的性能问题。2. 核心概念拆解Occluder与Occludee到底是谁在深入实操之前我们必须像认识新朋友一样把Occluder和Occludee这两个核心概念掰开揉碎了理解。很多误解都源于对它们基础定义的不清晰。2.1 Occluder场景中的“墙”与“盾牌”你可以把Occluder遮挡物想象成场景中一堵坚实的墙、一座大山或者一个巨大的集装箱。它的核心职责是挡住摄像机看向其后方物体的视线。在遮挡剔除的计算中Occluder是主动的“施法者”。关键特性实体性与封闭性一个理想的Occluder应该是一个视觉上“密不透风”的实体。从摄像机视角看过去它不应该有大的孔洞或缝隙。一堵完整的墙是完美的Occluder而一个铁丝网围栏则不是。相对尺寸Occluder需要在屏幕空间占有一定的面积才能有效地遮挡其后面的物体。一个非常细小的物体比如一根铅笔即使它处在其他物体前面也几乎无法在像素级别形成有效的遮挡将其标记为Occluder只会增加不必要的计算开销没有实际收益。不透明性这是最容易被忽略的一点。透明或半透明的物体如玻璃窗、粒子效果绝不能标记为Occluder。因为从逻辑上讲你能透过它看到后面的东西它就不具备“遮挡”的能力。如果强行标记Unity会认为它挡住了后面从而错误地剔除掉本应可见的物体导致画面错误。注意Occluder Static的勾选意味着你告诉Unity“这个物体在运行时不会移动、旋转或缩放并且它的形状足够‘结实’可以用来判断它后面有没有东西能被看到。” Unity在烘焙Bake遮挡数据时会将这些物体的几何信息用于计算可见性。2.2 Occludee场景中的“演员”与“道具”Occludee被遮挡物则是场景中那些可能被“墙”挡住的物体。比如墙后面的一个箱子、一座房子后面的树、或者巨大雕像脚下的一朵花。它的角色是被动的“承受者”。关键特性可被遮挡性标记为Occludee等于向Unity声明“我这个物体是可以被其他Occluder挡住的如果摄像机看不到我请放心地别渲染我。” 这是遮挡剔除能提升性能的根本——通过不渲染看不见的东西来节省GPU的绘制调用Draw Calls和像素着色开销。普遍性场景中绝大多数不透明的静态物体理论上都可以是Occludee。因为只要有一个足够大的Occluder在它前面它就有可能被挡住。与尺寸无关一个物体无论多小只要它是不透明的静态物体都可以是Occludee。因为即使是一个小石子也可能被一堵墙完全挡住。注意Occludee Static的勾选意味着你告诉Unity“这个物体是静态的并且你可以在判断它被其他Occluder完全挡住时安全地跳过对它的渲染。” 如果一个物体没有被勾选Occludee那么无论它前面有没有OccluderUnity在运行时都会认为它“永远可见”从而始终尝试渲染它这会使遮挡剔除对该物体完全失效。2.3 关系的核心非互斥且常共存这是最容易产生困惑的地方。从字面意思看“遮挡物”和“被遮挡物”像是一对反义词但在Unity的遮挡剔除系统中它们不是互斥的一个物体完全可以同时是Occluder和Occludee。为什么可以共存想象一下游戏场景中的一个石头房子。对于房子内部的家具而言房子的墙壁和屋顶是Occluder遮挡了家具。但同时这座房子本身也可能被更远处的一座大山另一个Occluder所遮挡。此时这座石头房子就同时扮演了两个角色对于它内部的家具它是Occluder。对于远处的大山它是Occludee。因此一个物体的“身份”是相对的取决于观察的层级关系。在复杂的场景中一个物体兼具两种身份是非常普遍的情况。官方文档推荐为许多物体同时勾选两者正是基于这种普遍的相对性。一个绝对不能共存的例外就是前面提到的透明物体。一个透明的物体如玻璃既不能有效地遮挡别人所以不应是Occluder同时它本身虽然可能被遮挡但将其标记为Occludee也可能有问题因为透明渲染通常依赖深度排序错误的剔除可能导致渲染顺序混乱。对于完全透明的物体最安全的做法是两个都不勾将其排除在静态遮挡剔除系统之外或者使用其他管理方式如按距离裁剪。3. 实战勾选策略从理论到场景配置理解了概念我们进入最关键的实战环节。面对场景中成百上千的物体究竟该如何决定每个物体Occluder Static和Occludee Static的勾选状态我总结了一个“四象限”分类法你可以对照着对你的场景资产进行快速归类。3.1 分类一大型、坚实、不透明的静态物体两者都勾这是最标准、最常见的一类。它们构成了场景的主体结构和视觉屏障。典型物体建筑的外墙、屋顶、地板。巨大的岩石、山体。厚重的集装箱、城堡的城墙。大型的不透明雕塑、纪念碑。勾选策略Occluder Static✅ Occludee Static✅原因分析它们体积大且封闭是完美的Occluder能有效遮挡其后方的大量物体如建筑内部的摆设、山后的树林。它们自身也可能被更大的物体遮挡例如一个小房子可能被一座大山挡住因此也需要作为Occludee参与计算。实操心得对于这类物体在导入Unity或制作预制体时就可以在模型文件的导入设置或预制体根节点上预先设置好Static标签包含Occlusion形成规范。这样可以避免在场景搭建后期一个个去勾选的繁琐。3.2 分类二小型、琐碎或不封闭的静态物体仅勾选Occludee这类物体通常作为场景的细节点缀它们本身不太可能去有效遮挡其他物体但自己却很容易被挡住。典型物体散落在地面上的小石块、瓶子、书本。栅栏、楼梯扶手有缝隙。链条、绳索非常细小。树叶茂密但透光的树冠视觉上不封闭。勾选策略Occluder Static❌ Occludee Static✅原因分析为何不是Occluder它们要么太小在屏幕上占据像素太少遮挡计算性价比极低要么本身有孔洞缝隙无法形成有效遮挡。将其标记为Occluder只会徒增烘焙时的计算量和运行时数据量而几乎不会带来任何有效的剔除优化。为何是Occludee它们完全可能被前面的墙壁、大型家具等物体挡住。当被挡住时我们当然希望系统能剔除它们以节省性能。注意这里有一个性能权衡。如果场景中有成千上万个这样的小物体即使只作为Occludee也会增加烘焙数据复杂度。此时可以考虑是否真的需要它们参与遮挡剔除。对于极远处或重要性极低的小物件或许可以通过LOD多层次细节或简单的视距裁剪来管理而不是依赖遮挡剔除。3.3 分类三透明、半透明或视效物体两者都不勾这类物体需要被特殊对待因为它们的视觉特性与遮挡剔除的基本假设不透明、实体相冲突。典型物体窗户玻璃、水幕、全息投影。粒子系统烟雾、火焰、魔法特效。使用了透明或镂空Shader的物体如铁丝网、树叶Billboard。仅用于触发事件的碰撞体Mesh Renderer被禁用但Collider启用。勾选策略Occluder Static❌ Occludee Static❌原因分析绝对不能是Occluder这是铁律。透明物体无法遮挡其后的物体。如果错误标记会导致其后方本应可见的物体被剔除画面出现“空洞”。谨慎作为Occludee透明物体的渲染依赖于正确的深度排序和混合。如果被遮挡剔除系统过早地决定其不可见可能会破坏渲染顺序导致视觉错误。对于完全动态的粒子特效其可见性更适合由粒子系统自身的生命周期和边界框Bounds来控制而非静态的遮挡数据。避坑技巧对于像“带窗格的窗户”这种物体需要拆解看待。窗框不透明部分可以按分类一处理而玻璃透明部分则应该单独分离成一个子物体并归为此类两者都不勾。确保在项目资源管理规范中明确这类特殊资产的Static设置要求。3.4 分类四特大背景或天空盒物体仅勾选Occluder或都不勾这类物体比较特殊通常是构成场景视觉边界的元素。典型物体环绕场景的远景山脉、天空盒几何体。永远不会被玩家“绕到后面去”的巨型背景板。勾选策略视情况而定通常Occluder Static✅ Occludee Static❌ 或者两者都不勾。原因分析与选择策略A作为Occluder如果这个背景物体如环绕的群山确实会遮挡其后面的其他景物比如山后面的云层贴图或更远的山脉那么它可以作为Occluder。但由于玩家永远不可能到这些山体的“后面”去它自己不存在“被遮挡”的可能因此Occludee无需勾选。策略B不作为Occluder如果这个背景物体只是一个纯粹的视觉背景例如一个半球形的天空穹顶它不会遮挡任何实际游戏内容因为所有内容都在它“内部”那么它作为Occluder没有意义。同时它也不可能被遮挡所以Occludee也无意义。此时两者都不勾将其排除在遮挡计算之外是最干净的。如何选择取决于你的场景构成。一个简单的判断方法是在场景中移动摄像机看这个背景物体是否曾处于其他游戏对象和摄像机之间并切实挡住了那些对象。如果是用策略A如果不是用策略B。为了更直观我将这四类策略总结成下表方便你快速查阅物体类型典型示例Occluder StaticOccludee Static核心原因与注意事项大型坚实不透明体建筑外墙、山体、厚墙✅✅是有效的遮挡物自身也可能被遮挡。主力优化对象。小型琐碎静态体小石块、瓶子、栅栏❌✅自身遮挡效果差标记为Occluder浪费资源但需要被剔除。透明/半透明/特效体玻璃、粒子、铁丝网❌❌透明物不能遮挡他物其渲染与剔除逻辑特殊需单独处理。特大背景/天空物体远景山、天空穹顶✅ 或 ❌❌若遮挡他物则勾Occluder若为纯背景则都不勾避免无意义计算。4. 工作流详解从场景准备到数据烘焙正确的勾选策略是基础但要让遮挡剔除真正高效工作还需要遵循一个完整的、可操作的工作流。下面我以创建一个室内小场景为例拆解每一步的操作和意图。4.1 第一步场景分析与初步标记在动手勾选任何复选框之前先花点时间在Scene视图中浏览你的场景。使用飞行模式按住鼠标右键WSAD快速穿梭从玩家可能的视角观察。识别主要遮挡体找出那些大型的、连续的墙体、地面和大型家具。在心里将它们归类为“分类一”。找出细节物体识别出所有小摆设、装饰品。将它们归类为“分类二”。揪出特殊物体找到所有透明材质、粒子发射器。将它们归类为“分类三”并确保它们的材质渲染模式Rendering Mode是Transparent或Fade。规划背景明确哪些是永远不会被穿过的背景元素决定处理策略分类四。4.2 第二步批量设置与层级管理Unity提供了强大的批量操作和层级Layer管理功能善用它们能极大提升效率。使用图层辅助选择在动手前可以规划几个专用图层如“Occluder_Static”、“Occludee_Only”、“Transparent_Ignore”。将物体按分类拖入相应图层。批量勾选Static在Hierarchy面板中可以通过图层过滤选择同一类物体。选中所有“分类一”的物体在Inspector右上角点击“Static”下拉菜单勾选“Occlusion Static”这会同时勾选Occluder和Occludee。对于“分类二”的物体批量勾选后需要手动取消其中的Occluder Static只保留Occludee Static。这可以通过编写一个小编辑器脚本批量完成或者使用一些第三方工具。检查预制体根节点如果大量物体来自预制体务必检查预制体根节点的Static设置。在预制体模式下设置好所有实例都会继承这是最规范的做法。4.3 第三步烘焙参数配置与执行打开Window Rendering Occlusion Culling面板这里才是决定烘焙质量和效率的核心。Occluder选项卡Smallest Occluder这是最重要的参数之一。它定义了能被当作Occluder的物体在屏幕上的最小像素尺寸。设置过高如100很多本应参与遮挡的中小型物体将被忽略导致剔除不精确。设置过低如2会把大量细小物体也纳入计算急剧增加烘焙时间和数据量得不偿失。我的经验值对于大多数第三人称或FPS游戏从10-20开始测试是一个不错的起点。对于俯视角或战略游戏可以设得更低如5因为单个物体在屏幕上可能更小。Smallest Hole定义Occluder上可以被忽略的“孔洞”的最大尺寸。如果一个物体上有比这个值小的缺口比如门上的钥匙孔系统会将其忽略仍视其为完整遮挡物。通常保持默认25即可除非你的场景有很多栅栏、网格这类物体。Bake选项卡View Cell Size这是另一个关键参数。它决定了将场景空间分割成的“细胞”大小。值越小剔除精度越高但烘焙数据量越大运行时查询开销也略增。值越大数据量小但精度低可能导致物体在应该出现时延迟出现“ popping in”。建议对于室内场景或复杂城市可以设为1-2米对于广阔的野外地形可以设为5-10米甚至更大。可以先使用一个较大的值如5快速烘焙测试观察剔除效果再逐步调小。Save As务必为烘焙结果指定一个名称并保存到项目中如“SceneName_OcclusionData”。否则数据不会持久化。烘焙操作点击Bake按钮。在Console窗口会看到进度。烘焙时间从几秒到几十分钟不等取决于场景复杂度、参数设置和电脑性能。4.4 第四步验证与调试烘焙完成不是终点必须验证效果。在Scene视图验证在Occlusion Culling窗口确保Visualization模式是打开的。在Scene视图中你会看到被剔除的物体以红色线框显示默认。移动摄像机观察红色物体的出现和消失是否符合逻辑。特别注意透明物体附近看是否有不该消失的物体被错误剔除。使用相机预览在Game视图选中主摄像机在Inspector中找到Occlusion Culling选项并勾选。这样在Game视图也能看到剔除效果。同时你可以启用摄像机的Occlusion Culling调试视图通过脚本或插件在运行时直观查看。性能分析使用Unity Profiler的Rendering模块对比开启和关闭遮挡剔除时的Batches批处理次数和SetPass Calls的变化。一个有效的遮挡剔除应该能显著减少这些数值尤其是在摄像机面向复杂区域时。5. 常见问题排查与性能陷阱即使按照上述流程操作在实际项目中你还是可能会遇到各种奇怪的问题。下面是我踩过的一些坑以及解决方法。5.1 问题一烘焙后物体在应该可见时被错误剔除“穿帮”这是最严重的问题直接导致画面错误。可能原因及排查透明物体被误标为Occluder这是头号嫌犯。检查所有透明物体玻璃、水、粒子系统的Static标记确保Occluder Static没有被勾选。补救立即取消勾选并重新烘焙受影响区域可以使用Bake按钮下的Clear后再Bake或使用增量烘焙。Occluder物体有“裂缝”或非闭合如果一个应该作为遮挡的墙体模型本身有微小的裂缝或不是水密watertight的遮挡计算可能会从裂缝中“泄漏”导致其后的物体被意外剔除。排查在3D建模软件中检查模型完整性或尝试在Unity中为该物体添加一个简单的Box Collider并临时用这个Collider代替Mesh作为Occluder进行烘焙测试通过修改烘焙设置。Smallest Hole参数过大如果Occluder上存在比Smallest Hole参数更大的真实开口如窗户系统会错误地将其视为遮挡物的一部分从而剔除窗后的物体。解决减小Smallest Hole值或更好的方法是将带窗的墙体拆分成“窗框”Occluder和“窗洞”空区域两部分来处理。物体缩放为负值或极端值物体的Transform Scale如果为负或非常极端如0.001可能会导致其包围盒Bounds计算异常进而影响遮挡计算。解决规范资产导入和场景摆放避免使用非均匀缩放或负值缩放。5.2 问题二遮挡剔除似乎没效果性能没有提升烘焙完成了但Profiler里的Draw Calls并没减少。可能原因及排查摄像机视锥体Frustum裁剪已足够如果你的场景本身开阔物体分布稀疏大部分性能消耗可能已经在视锥体裁剪阶段被优化掉了遮挡剔除的用武之地不大。这是正常现象说明你的场景设计本身对渲染友好。Occludee Static未勾选这是常见疏忽。很多物体只勾了Occluder忘了勾Occludee。这意味着它们可以去挡别人但自己永远不会被剔除。检查批量检查中小型物体的Static设置。Smallest Occluder值设得过高导致场景中有效的Occluder太少没有足够的遮挡物去剔除后面的Occludee。尝试逐步调低此参数如从50调到20观察剔除效果的变化。注意平衡精度和烘焙成本。动态物体过多遮挡剔除只对标记为Occlusion Static的物体生效。如果你的场景中充满了动态移动的物体NPC、可移动道具它们无法被静态遮挡剔除优化。此时需要考虑其他优化手段如动态遮挡剔除如Unity的Occlusion Portal但更常用于大型动态场景如MMO、基于距离的LOD或简单的视距管理。5.3 问题三烘焙时间过长或数据文件巨大可能原因及排查场景复杂度过高面数太多、物体数量太多是根本原因。优化在烘焙前务必使用LOD Group为远处物体设置低模合并Merge静态的、材质相同的小物体减少Draw Calls和物体数量检查是否有不必要的细分网格。View Cell Size过小这是导致数据膨胀的主要原因。将View Cell Size从0.5提高到1.0数据量可能减少一个数量级而剔除精度在大多数情况下仍可接受。建议永远从较大的View Cell Size开始测试。过多细小物体被标记为Occluder回顾我们的分类大量“分类二”的物体如果错误标记了Occluder Static会极大地增加烘焙复杂度。纠正严格按照分类策略清理Static标记。烘焙范围过大检查场景中是否有位于很远处的、无关紧要的物体。可以适当调整烘焙的包围盒范围或者将这些物体移到另一个场景中按需加载。5.4 性能陷阱过度使用Static的连锁反应错误地滥用Static复选框影响的远不止遮挡剔除。静态批处理Static Batching的代价当你勾选Static时默认也会启用静态批处理。它会将多个静态、同材质的物体合并成一个大的网格进行绘制减少Draw Calls。但是这个合并过程会增加内存占用存储合并后的网格并且合并后的网格如果很大可能会破坏GPU的视锥体裁剪效率因为只要网格的任何一部分在视锥体内整个大网格都会被提交渲染。对于大量重复的小物体如草地、碎石静态批处理是福音但对于少数几个巨大的独特静态物体合并可能弊大于利。导航网格Navigation Static的误用如果你同时勾选了Navigation Static这些物体会被纳入导航网格的烘焙计算。将大量细小装饰品或玩家根本不会走上去的物体如吊灯标记为可导航会不必要地增加导航网格的复杂度和烘焙时间。光照贴图Lightmap Static的牵连同理错误的Lightmap Static标记会导致光照贴图包含本不该包含的物体增加光照烘焙时间和贴图尺寸。最佳实践建议不要无脑全选场景物体然后勾上Static。应该使用Static的下拉菜单精确地、分门别类地勾选你需要的优化选项。例如一个只用于遮挡的巨型背景山体可能只需要勾选Occlusion Static而不需要勾选Navigation Static和Lightmap Static如果它不受场景光照影响。