找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

249

积分

0

好友

29

主题
发表于 15 小时前 | 查看: 2| 回复: 0

在游戏开发中,提升渲染效率最直接的方法就是避免渲染不可见的物体。Unity引擎为此提供了多种渲染剔除(Culling)技术,以优化性能、降低Draw Call和减少Overdraw。

Unity中的三大渲染剔除技术

视锥体剔除(Frustum Culling)

这是引擎自动执行的基础剔除。它利用场景管理算法(2D用四叉树,3D用八叉树)快速收集位于摄像机视锥体(Frustum)内的物体,构成“潜在可见集”。此过程计算开销较大,但不可或缺。

对于需要反射的场景(如镜子、水面),传统方法需要创建额外的反射摄像机并进行同样昂贵的裁剪计算。Unity提供了Reflection Probe组件来离线烘焙静态反射数据,以优化这一过程。

遮挡剔除(Occlusion Culling)

进入视锥体的物体未必最终对玩家可见(例如被一堵墙完全遮挡的雕像)。渲染这些物体是无效的性能开销。遮挡剔除技术通过将场景划分为网格单元,并预先计算每个摄像机可能位置(View Cell)的可见物体集合(Target Cell),在运行时快速查询并仅渲染真正可见的物体,从而显著提升性能。这涉及到复杂的离线烘焙与运行时查询,是性能优化的关键。

摄像机距离剔除(Camera Layer Cull Distance)

此功能允许你为不同的Layer设置摄像机最大可见距离。超出设定距离的该层物体将不被渲染,非常适合用于处理地面装饰物(如小石头、草皮)等细节。

启用方法是为摄像机脚本设置 layerCullDistances 数组:

Camera camera = GetComponent<Camera>();
float[] distances = new float[32];
// 设置名为“Npc”的Layer的剔除距离为11个单位
distances[LayerMask.NameToLayer("Npc")] = 11;
camera.layerCullDistances = distances;
// 启用球面剔除,使得距离判断更符合3D空间逻辑,避免相机转动时物体突兀消失
camera.layerCullSpherical = true;

深度剖析:遮挡剔除(Occlusion Culling)实战

遮挡剔除的核心目标是解决过度绘制(Overdraw)问题,即同一个像素被多次绘制(远处的物体先被绘制,随后被近处物体覆盖)。通过确保只将最终可见的物体送入渲染管线,可以大幅降低GPU负载和Draw Call。

下图展示了未经任何剔除时,所有物体都被渲染的低效情况:
深度解析Unity引擎性能优化:全面掌握遮挡剔除Occlusion Culling技术 - 图片 - 1

应用视锥体剔除后,大量屏幕外的物体被剔除,渲染负载显著降低:
深度解析Unity引擎性能优化:全面掌握遮挡剔除Occlusion Culling技术 - 图片 - 2

最后,应用遮挡剔除,仅渲染摄像机实际能看到的物体,这是最理想的高效状态。掌握这类优化手段,是构建高性能应用和云原生/IaaS服务后端逻辑的基础,都体现了对资源(无论是GPU还是CPU/内存)的高效管理思想。
深度解析Unity引擎性能优化:全面掌握遮挡剔除Occlusion Culling技术 - 图片 - 3

你可以在Scene视图中选择“OverDraw”渲染模式来可视化过度绘制,并在Game视图的Stats面板中查看渲染的三角形总数和批处理次数。

下图未启用遮挡剔除,注意Scene视图中的严重过度绘制(墙后大量房间被渲染),尽管它们在Game视图中完全不可见。
深度解析Unity引擎性能优化:全面掌握遮挡剔除Occlusion Culling技术 - 图片 - 4

启用遮挡剔除后,远处被遮挡的房间不再渲染,过度绘制大幅减少,绘制的三角形数量和批处理次数也显著下降。
深度解析Unity引擎性能优化:全面掌握遮挡剔除Occlusion Culling技术 - 图片 - 5

第一步:设置静态物体(Occluder Static / Occludee Static)

要让物体参与遮挡剔除,需要将其标记为“静态”。在Inspector面板的右上角Static下拉框中,勾选 Occluder StaticOccludee Static

深度解析Unity引擎性能优化:全面掌握遮挡剔除Occlusion Culling技术 - 图片 - 6

  • Occluder Static:大型物体,会遮挡其他物体(如墙壁、山脉)。
  • Occludee Static:小型物体,通常被其他物体遮挡(如房间内的家具、道具)。

最佳实践:将关卡结构分解为合适的大小。大的遮蔽物(墙壁)应设置为Occluder,而被遮蔽的小物体群(如房间内的多个家具)应分别设置,而不是合并为一个整体,以获取更精细的剔除效果。使用LOD Group时,仅LOD0层级会被视为遮挡物。

第二步:使用遮挡剔除窗口

通过 Window > Rendering > Occlusion Culling 打开窗口。窗口包含三个面板:Object、Bake、Visualization。

Object 面板中,可以在场景中选择物体并设置其遮挡类型。
深度解析Unity引擎性能优化:全面掌握遮挡剔除Occlusion Culling技术 - 图片 - 7

如果选择了遮挡区域(Occlusion Area),则可以在此修改其属性。
深度解析Unity引擎性能优化:全面掌握遮挡剔除Occlusion Culling技术 - 图片 - 8

重要提示:如果不创建任何Occlusion Area,烘焙将应用于整个场景。务必确保Occlusion Area完全覆盖摄像机所有可能移动到的区域,否则摄像机离开区域后剔除会失效。但过大的区域会增加烘焙时间。

第三步:烘焙(Bake)遮挡数据

切换到 Bake 面板进行参数设置和烘焙。
深度解析Unity引擎性能优化:全面掌握遮挡剔除Occlusion Culling技术 - 图片 - 9

点击 Set default parameters 可使用适用于大多数场景的默认值。你也可以手动调整以适配特定场景:

参数 说明
Smallest Occluder 能够遮挡其他物体的最小尺寸。小于此值的物体将不会遮挡他物。用于平衡剔除精度与数据量。
Smallest Hole 摄像机视线可以穿透的两个几何体之间的最小“孔洞”直径。
Backface Threshold 背面剔除阈值。通过忽略摄像机永远不会到达的区域(如地形内部)来优化数据量。值越低,优化越激进。

面板底部的 Bake 按钮用于开始生成数据,Clear 用于清除已有数据。烘焙完成后,可以切换到 Visualization 面板预览效果。

第四步:为移动物体创建Occlusion Area

对于动态(非静态)物体,需要创建 Occlusion Area 来定义其活动范围。为一个空GameObject添加 Occlusion Area 组件即可创建。

深度解析Unity引擎性能优化:全面掌握遮挡剔除Occlusion Culling技术 - 图片 - 10

创建后,在Inspector中调整其 SizeCenter,并勾选 Is View Volume,以使其能对移动物体进行遮挡剔除。

深度解析Unity引擎性能优化:全面掌握遮挡剔除Occlusion Culling技术 - 图片 - 11

第五步:测试与调试

烘焙后,在 Occlusion Culling 窗口的 Visualization 面板中,勾选 Occlusion Culling

深度解析Unity引擎性能优化:全面掌握遮挡剔除Occlusion Culling技术 - 图片 - 12

在Scene视图中移动摄像机(可在非运行模式下),被剔除的物体会显示为红色(或不可见)。你应该检查是否有物体“突然弹出”(Pop-in),这通常意味着遮挡数据有误或物体设置不当。

烘焙数据以彩色立方体形式可视化:

  • 蓝色立方体:代表Target Cells(被遮挡物体的网格划分)。
  • 白色立方体:代表View Cells(摄像机位置区域的网格划分)。

如果在测试中发现没有物体被剔除,可能需要将大型物体拆分为更小的部分,以确保它们能被单个Cell完全包含,或者重新审视你的场景划分和参数设置策略,这就像优化算法/数据结构一样,需要找到数据组织与查询效率的最佳平衡点。




上一篇:addr2line实战:Linux C++崩溃地址定位与线上调试指南
下一篇:Vue Router路由模式对比:hash与history工作原理、应用场景与配置指南
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-24 17:19 , Processed in 0.151217 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表