浅谈Unity物理性能优化(2) Mesh Collider优化

1,588 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情

Mesh Collider的烘焙

物理引擎运行时通常分为Broad phaseNarrow phase这两个步骤。Broad phase收集可能发生的潜在碰撞,然后将之发送到Narrow phase,在这里进行真正的碰撞计算。当生成Mesh Collider中使用的运行时mesh时,重要的是要为mesh生成合适的三角形。物理引擎使用的模型通常要经过一个烘焙过程,在这个过程中会创建物理查询所需的优化空间结构。

烘焙选项

对于预先制作的物理模型,Unity的默认Cooking选项就是最佳的选择,默认的选项为Everyting,这包含:

  • Cook for Faster Simulation 为物理模拟优化物理模型,如果不使用可以缩短烘焙时间。
  • Enable Mesh Cleaning 去除退化的三角形以及其他几何瑕疵,这有助于更好的计算碰撞检测。
  • Weld Colocated Vertices 焊接重叠的顶点
  • Use Fast Midphase 针对当前平台使用最佳的加速结构和算法

程序生成物理模型的烘焙时间优化

由于这些烘焙选项都会增加烘焙时间,对于程序在运行时生成的物理模型,如果能保证不产生退化三角形就可以关闭Enable Mesh Cleaning,如果能保证不产生位置重叠的顶点就可以关闭Weld Colocated Vertices

使用Job System优化运行时烘焙

对于程序生成物理模型这种需要在运行时进行的烘焙,可以使用Job System进行加速,让烘焙在主线程之外的其他线程进行,并且可以多个线程同时烘焙多个模型。

  • 首先,定义一个BakeMeshJob
using Unity.Burst;
using Unity.Jobs;
using Unity.Collections;
using UnityEngine;

[BurstCompile]
public struct BakeMeshJob : IJobParallelFor
{
    [ReadOnly]
    [DeallocateOnJobCompletion]
    public NativeArray<int> MeshIds;
    
    public void Execute(int index)
    {
        Physics.BakeMesh(MeshIds[index], false);
    }
}

这个Job使用Mesh ID来调用Physics.BakeMesh来烘焙物理模型。因此在启动job时需要指定Mesh ID的数组。

  • 调度Job
var ids = new NativeArray<int>(1, Allocator.TempJob);
ids[0] = meshes[0].GetInstanceID();
var bakeJobHandle = new BakeMeshJob {
    MeshIds = ids
}.Schedule(1, 1, bakeJobHandle);
  • 等待Job完成 一般在使用Job System时,我们会在一帧的末尾去调度Job,而在下一帧的开始去等待Job完成,这样可以缩短等待的时间,因为一帧末尾调度Job会让Job线程去执行该Job,同时,该帧在主线程上已经计算完毕了,下面就是等待GPU渲染完成,因此Job的执行和GPU的执行可以看成是同步的,等GPU渲染完毕进入下一帧,Job也已经完成或者差不多该完成了,此时再去执行Complete确认他完成,就可以减少等待的时间。
void Update()
{
    //一帧的开始,先确认Job完成
    bakeJodHandle.Complete();
    
    //其他逻辑
}

Prebake Collision Meshes

这是Unity Player Setting中的一个优化选项:

image.png

注意,这儿的Prebake并不是上面说的烘焙Mesh Collider。Unity使用的物理引擎是Physx,Physx对于mesh collider需要计算一个physx mesh内部的表示,默认情况下,是在load关卡时计算的。如果使用LoadLevelAsync异步载入,则这些计算不会影响帧率,但是会增加一些load时间。如果勾选此选项,则Unity会在Build时进行这个计算,特别是当有多个物体使用相同的物理模型,且物理模型最终只会均匀缩放,这些物体就可以共享物理模型,开启选项后,在build时就可以让这些物体引用同一个physx mesh。从而大大节省loading时间。