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或者没有自动隐藏的程序,不要做开放地图。

相关推荐
笑鸿的学习笔记41 分钟前
虚幻引擎5-Unreal Engine笔记之SET节点的输出引脚获取设置后的最新变量值
笔记·ue5·虚幻
草莓熊Lotso1 小时前
【数据结构初阶】--算法复杂度的深度解析
c语言·开发语言·数据结构·经验分享·笔记·其他·算法
快乐觉主吖1 小时前
Unity的日志管理类
android·unity·游戏引擎
东京老树根1 小时前
SAP学习笔记 - 开发27 - 前端Fiori开发 Routing and Navigation(路由和导航)
笔记·学习
UQI-LIUWJ3 小时前
LLM 笔记:Speculative Decoding 投机采样
笔记
凤年徐5 小时前
【数据结构初阶】单链表
c语言·开发语言·数据结构·c++·经验分享·笔记·链表
阿阳微客7 小时前
Steam 搬砖项目深度拆解:从抵触到真香的转型之路
前端·笔记·学习·游戏
px不是xp11 小时前
山东大学算法设计与分析复习笔记
笔记·算法·贪心算法·动态规划·图搜索算法
echo haha12 小时前
第7章 :面向对象
笔记