meshID | 用于烘焙碰撞数据的网格的实例化 ID。 |
convex | 一个标志,指示是否烘焙凸几何。 |
准备用于 网格碰撞器 的网格,并使用默认烹饪选项。
meshID | 用于烘焙碰撞数据的网格的实例化 ID。 |
convex | 一个标志,指示是否烘焙凸几何。 |
cookingOptions | 烘焙网格时使用的烹饪选项。 |
准备用于 网格碰撞器 的网格。
为了让网格可与 网格碰撞器 一起使用,物理系统必须先准备它,方法是创建空间搜索加速结构。此过程称为烘焙。
通常,网格碰撞器组件在用户实例化它时或在用户使用 sharedMesh 属性向其设置新网格时需要烘焙的网格。烘焙是一个资源密集型操作,因此您可能需要在时机合适时(例如在应用程序资源密集程度较低的部分)运行它,或者在所有可用内核间分散负载(如果有多个网格需要烘焙的话)。话虽如此,此函数的目的是预先烘焙网格以供以后使用,以免需要再次烘焙。
网格实例存储烘焙的网格。
烘焙过程需要访问网格几何。如果用户在播放器中调用 BakeMesh 方法,则 BakeMesh 方法需要启用网格的读写属性。但是,在编辑器中使用 BakeMesh 方法不需要任何额外的设置,因为几何始终在编辑器中可用。
当且仅当满足以下所有条件时,网格碰撞器组件才会重复使用烘焙网格
在此上下文中,网格碰撞器的变换允许共享网格,如果
注意:当您将 MeshCollider 组件添加到已存在 MeshFilter 组件的游戏对象时,sharedMesh 属性会自动设置,这可能会触发重新烘焙。
以下是一个简单的示例,在主线程上烘焙网格
using UnityEngine;
public class MinimalTest : MonoBehaviour { public Mesh mesh;
private MeshCollider collider;
private MeshColliderCookingOptions cookingOptions = MeshColliderCookingOptions.UseFastMidphase & MeshColliderCookingOptions.CookForFasterSimulation;
private void OnEnable() { // Bake this Mesh to use later. Physics.BakeMesh(mesh.GetInstanceID(), false, cookingOptions); }
public void FixedUpdate() { // If the collider wasn't yet created - create it now. if (collider == null) { // No mesh baking will happen here because the mesh was pre-baked, making instantiation faster. collider = new GameObject().AddComponent<MeshCollider>(); collider.cookingOptions = cookingOptions; collider.sharedMesh = mesh; } } }
BakeMesh 是线程安全的,并在其被调用所在的线程上执行计算。但是,不要同时从多个线程中对同一网格调用 BakeMesh,因为这会导致未定义的行为。您可以将 BakeMesh 与 C# 作业系统结合使用。此示例展示如何在多个线程上烘焙网格,以便在主线程上花费更少的时间实例化网格碰撞器。
using Unity.Collections; using Unity.Jobs; using UnityEngine;
public struct BakeJob : IJobParallelFor { private NativeArray<int> meshIds;
public BakeJob(NativeArray<int> meshIds) { this.meshIds = meshIds; }
public void Execute(int index) { Physics.BakeMesh(meshIds[index], false); } }
public class JobifiedBaking : MonoBehaviour { public Mesh[] meshes; public int meshesPerJob = 10;
// Bake all the Meshes off of the main thread, and then instantiate on the main thread. private void OnEnable() { // You cannot access GameObjects and Components from other threads directly. // As such, you need to create a native array of instance IDs that BakeMesh will accept. NativeArray<int> meshIds = new NativeArray<int>(meshes.Length, Allocator.TempJob);
for (int i = 0; i < meshes.Length; ++i) { meshIds[i] = meshes[i].GetInstanceID(); }
// This spreads the expensive operation over all cores. var job = new BakeJob(meshIds); job.Schedule(meshIds.Length, meshesPerJob).Complete();
meshIds.Dispose();
// Now instantiate colliders on the main thread. for (int i = 0; i < meshes.Length; ++i) { new GameObject().AddComponent<MeshCollider>().sharedMesh = meshes[i]; } } }