Unity LODGroup详解
【LOD】
LOD(Level of Detail,层次细节) 是优化3D模型渲染性能的核心技术,LOD 的核心思想:物体在屏幕上占用像素少时,用更低精度的模型(或直接不渲染)以节省 CPU/GPU/内存开销;在接近摄像机时用高精度模型以保证画质
通常最高等级是LOD0,随后可以依次是LOD1、LOD2、LOD3、LOD4,一般0~4共五个等级基本够用
(在理解上,可以认为不同LOD等级是不同的模型,只是形状相似,必要时也可以不相似)
不同LOD等级的区别在于模型三角面数,三角面少有利于提高渲染性能
通常会先做出LOD0的高精模型,通过一些减面技术(建模软件会内置)得到其余等级的模型
此外,也可能需要为不同模型准备不同的材质或贴图
LOD的核心在于切换策略,最简单的策略是:物体与摄像机的距离
在Unity中使用LODGroup组件可以实现LOD切换,其以“屏幕相对高度”(screen relative height)为依据,其是物体包围球(或包围盒)的投影大小与屏幕高度的比值
每个 LOD 有一个阈值(Inspector 中为滑条),当物体在屏幕上的相对高度小于该阈值时,会切换到下一个 LOD
注意,切换是每帧基于当前渲染相机计算的,因此多摄像机场景下不同摄像机可能看到不同的 LOD
【使用】
LODGroup使用struct LOD来记录不同等级LOD的数据,核心是两个数据:
- public float screenRelativeTransitionHeight;//屏占比
- public Renderer[] renderers;//渲染器
通过SetLODs接口设置LODGroup所管理的LOD,设置为空意味着删除
SetLODs(List<LOD> lodList, int index, int count, bool updateBoundsByLOD0)
可以根据游戏策略给不同角色设置不同的LOD等级
通过GetLODs可以获取当前设置的LOD
通过ForceLOD(int index)强制显示某个等级的LOD,停止自动切。传入-1时再开启自动切换
localReferencePoint 是 LODGroup 用来做距离 / 屏幕覆盖计算的“基准点”,以 LODGroup 的本地坐标(local space)表示
Unity 在选择某个 LOD 时,会把这个本地点变换到世界空间(transform.TransformPoint(localReferencePoint)),然后以相机到该世界点的距离(与屏幕覆盖计算相关)来决定应该显示哪个 LOD
默认情形下,这个点通常是基于模型/渲染器的中心计算出来的(或者为 (0,0,0)),可以在 Inspector 或脚本中手动设置它
如果模型的几何中心与 Transform 的 pivot 有较大偏移,或者模型由多个分散的 renderers 组成,默认参考点可能并不是期望的“视觉中心”。这会导致 LOD 提前或延后切换。修改 localReferencePoint 可以把“测距点”移动到比 pivot 更合理的位置(例如角色的胸口、对象几何中心、摄像机更常接近的部分等)例如:
- 一个长长的物体(火车、有长杆子的模型),pivot 在一端:把参考点移到模型中部/中心,可以避免摄像机接近另一端时仍然使用远距离 LOD
- 多个 renderer 分散布局(树群、复杂道具):把参考点设为所有 renderer 的包围盒中心
- 想让某个部分先显示高模:把参考点移动到该部分靠近相机的一侧
QualitySettings.lodBias会影响全局LOD缩放判定
Unity 在决定使用哪个 LOD 时会比较物体的屏幕相对高度(objectScreenSize)与每级 LOD 的阈值。实际比较时会把 objectScreenSize 乘以 QualitySettings.lodBias:effectiveSize = objectScreenSize * QualitySettings.lodBias然后用 effectiveSize 与各 LOD 的 screenRelativeTransitionHeight 比较
lodBias > 1:把物体看得更“大”,高精度 LOD 会在更远处保留(更晚降级 → 更好画质,但性能开销更高)
lodBias < 1:把物体看得更“小”,更早降级到低精度 LOD(性能更好但画质下降)
建议保持为正数(通常 0.5、1、2 等),避免设置为 0 或负数
在性能/画质需要平衡时通过 QualitySettings.lodBias 调整整体 LOD 行为,而无需单独改每个模型的阈值
【切换方式】
一般来说,切换都会涉及平滑的问题,硬切在视觉上会导致抖动。
LODGroup提供CrossFade和SpeedTree两种平滑切换方式
CrossFade的实现是通过同时渲染两个 LOD,并调整它们的透明度来平滑过渡,其通过确切的时间做后置切换,通过LODGroup.crossFadeAnimationDuration设置切换时间
也可以禁用时间切换,通过设置LOD的Fade Transition Width做自定义切换
但 CrossFade的切换方式会增加额外的渲染开销,移动端慎用
如果是SpeedTree制作的模型,SpeedTree 几何体存储每个顶点的下一个 LOD 位置,每个顶点都知道如何在当前 LOD 位置与下一个 LOD 位置之间进行插值,过渡会交给 SpeedTree 的着色器/运行时处理。这种方式用的不多。
更进一步的来说,我们可以根据游戏的特点综合更多的因素,自己动态切换LOD。这些因素包括:距离、视角、转速、屏幕像素占比等
【HLOD简介】
普通 LOD(LODGroup)通常是单个对象按距离切换几组网格,关注单体细节。
HLOD(Hierarchical Level Of Detail,分层细节层级),把多个对象当成一个整体来做 LOD,解决的是 draw call、材质切换和大范围场景的整体开销,而不仅仅是单个模型的三角数。
通常先分层Hierarchy,把场景划分成树状层级(小组 → 更大组 → ...),每个层级都有自己的 LOD(高细节到低细节)。
然后聚合Clustering,在某一层级把多个独立网格合并成一个或少数几个代理网格,以减少 draw call 和批次开销,同时不同层级的代理可以有更简化的贴图、材质,可以做材质贴图的合并
HLOD的切换策略和LODGroup大体相似,由于是针对多组对象的,HLOD的使用相比原来会降低内存。但可能也会导致多余的物体Mesh被加载而增大内存。
通常可用于以下静态场景:
- 开放世界/大地图:城市、山地、植被密集地区,将远处建筑/树群合并为代理
- 视距外的复杂物体群:群集小物件(石堆、杂物)在远处用单一代理替换
【参考】
https://docs.unity3d.com/cn/2023.2/Manual/class-LODGroup.html
