Unity性能优化笔记

降低Draw Call

降低draw call(unity里叫batches)的方法有:

模型减少材质;

多模型共用材质;

烘焙灯光;

关闭阴影和雾;

遮挡剔除;

使用LOD;

模型减少材质

>

见blender烘焙贴图的文章。

遮挡剔除

在测试中遇到了1400次draw call的情况。把运行暂停,把场景里的对象分组失活,发现:

失活城镇3:1402>1119。失活城镇1:1397>953。此处城镇1是相机视野内的但是离得很远已经被地形完全挡住的城镇,但是造成了400多次Draw Call

直接问deepseek:

在 Unity 中,要让被地形遮挡的物体不调用 Draw Call,需要通过 **遮挡剔除(Occlusion Culling)** 技术实现。以下是完整的实现步骤和优化方法:


**一、核心原理**

  • **遮挡剔除(Occlusion Culling)**:通过预计算或运行时检测,跳过对相机视野中**被其他物体完全遮挡的物体**的渲染,从而减少 Draw Call 和 GPU 负载。

  • **地形作为遮挡体**:将地形标记为遮挡物(Occluder),其他物体标记为被遮挡物(Occludee),Unity 会自动处理遮挡关系。


**二、实现步骤**

1. **启用遮挡剔除**

  • 打开 **Window > Rendering > Occlusion Culling**。

  • 在 **Bake** 选项卡中,确保 **Occlusion Culling** 功能已启用。

2. **标记静态物体**

3. **烘焙遮挡数据**

  • 在 **Occlusion Culling** 窗口的 **Bake** 选项卡中调整参数:

  • **Smallest Occluder**:设置地形细节级别(例如 `10`,单位:米,值越小精度越高)。

  • **Smallest Hole**:遮挡孔洞的最小尺寸(通常保持默认 `0.25`)。

  • 点击 **Bake** 生成遮挡数据,完成后会在场景中生成 **Occlusion Culling Data** 文件。

4. **验证效果**

  • 在 Scene 视图顶部下拉菜单中选择 **Occlusion Culling** > **Visualization**。

  • 移动相机,被地形遮挡的物体会显示为**红色(未渲染)**,可见物体为**绿色(已渲染)**。


**三、动态物体的处理**

若需要被遮挡的物体是动态的(如移动的敌人),需结合以下方法:

1. **脚本检测遮挡**

```csharp

using UnityEngine;

public class DynamicOcclusion : MonoBehaviour {

private Renderer rend;

void Start() {

rend = GetComponent<Renderer>();

}

void Update() {

// 检测物体是否被地形遮挡

if (Camera.main != null) {

Vector3 viewportPos = Camera.main.WorldToViewportPoint(transform.position);

bool isVisible = GeometryUtility.TestPlanesAABB(

GeometryUtility.CalculateFrustumPlanes(Camera.main),

rend.bounds

);

rend.enabled = isVisible; // 根据可见性开关渲染器

}

}

}

```

  • 将此脚本附加到动态物体上,根据可见性动态启用/禁用渲染。

2. **LOD(细节层次)配合**

  • 对中远距离物体使用低模(LOD1/LOD2),减少被遮挡时的计算开销。

**四、注意事项**

  1. **遮挡烘焙参数优化**
  • **Smallest Occluder** 值过大可能导致小物体无法遮挡其他物体,建议根据场景比例调整。

  • 复杂场景可分层烘焙:先烘焙地形,再烘焙建筑等大型物体。

  1. **性能权衡**
  • 遮挡剔除的预计算需要时间,适合静态场景。

  • 动态遮挡(如上述脚本)会增加 CPU 开销,需测试平衡。

  1. **地形设置**
  • 确保地形的碰撞体(Collider)完整,否则可能无法正确遮挡。

**五、常见问题**

Q1:烘焙后遮挡无效?

  • 检查物体是否标记为 **Occludee Static**。

  • 调整 **Smallest Occluder** 值,确保小于遮挡物的尺寸。

Q2:如何减少遮挡数据体积?

  • 增大 **Smallest Occluder** 和 **Smallest Hole** 的值。

  • 移除不必要的静态物体标记。


**六、替代方案**

  • **视锥体剔除(Frustum Culling)**:Unity 默认启用,仅渲染相机视锥体内的物体。

  • **硬件遮挡查询(Hardware Occlusion Query)**:适合高端设备,但需手动实现。

通过合理配置遮挡剔除,可显著减少地形遮挡区域的 Draw Call,尤其适用于开放世界或复杂室内场景! 🌟

照做之后在遮挡剔除Visualization看效果。远方有一些房子被剔除了,还有一些应该剔除的没剔除。这时候再运行,看向远方的小镇,batches最多只有700多次了,失活远方小镇batches还会降到500多次。然后就研究调整参数把这几个房子也剔除了。

URP项目动态合批设置的位置

Unity性能优化篇(三) SRP/URP动态合批开启与注意事项_unity 开启动态合批-CSDN博客

偏好>Core Render Pipeline>All Visible>项目设置>Graphics>Scriptable Render Pipeline Settings>Rendering

开放地图的性能优化

已经知道玩家视野里远方的物体会增加巨量不必要的draw call,遮挡剔除第一可能剃不干净,第二如果玩家在视野开阔的地方,远方的物体没有被遮挡,遮挡剔除也没有用,此时只能用LOD。

所以,如果场景物体没有LOD或者没有自动隐藏的程序,不要做开放地图。

相关推荐
fmk10231 小时前
TailwindCSS 学习笔记
笔记·学习
摇滚侠1 小时前
Vue 项目实战《尚医通》,完成确定挂号业务,笔记46
java·开发语言·javascript·vue.js·笔记
摇滚侠2 小时前
Vue 项目实战《尚医通》,完成取消预约业务,笔记49
vue.js·笔记
Just right2 小时前
AndroidApp笔记环境配置
笔记
xinxingrs2 小时前
贪心算法、动态规划以及相关应用(python)
笔记·python·学习·算法·贪心算法·动态规划
四谎真好看3 小时前
Java 黑马程序员学习笔记(进阶篇28)
java·笔记·学习·学习笔记
Oll Correct3 小时前
Excel基础操作(二)
笔记·excel
hd51cc3 小时前
文档与视图 学习笔记
笔记·学习
毛甘木5 小时前
Unity MonoPInvokeCallback 使用教程
c++·unity
chenzhou__6 小时前
LinuxC语言并发程序笔记(第二十天)
linux·c语言·笔记·学习