[RequireComponent(typeof(MeshCollider))]
public class MeshCompositeCollider : MonoBehaviour
{
void Start()
{
var meshColliders = GetComponentsInChildren<MeshCollider>();
var combine = new CombineInstance[meshColliders.Length];
for (int i = 0; i < meshColliders.Length; i++)
{
combine[i].mesh = meshColliders[i].sharedMesh;
combine[i].transform = meshColliders[i].transform.localToWorldMatrix;
meshColliders[i].enabled = false;
}
var compositeMesh = new Mesh();
compositeMesh.CombineMeshes(combine);
//WeldVertices(compositeMesh);
GetComponent<MeshCollider>().sharedMesh = compositeMesh;
GetComponent<MeshCollider>().enabled = true;
}
}
需要注意的一点是:合并后的网格是以世界空间坐标为基础的,因此如果这个游戏对象有任何变换改变,它们也会被应用。
如果您启用了 MeshCollider -> Cooking Options -> 焊接重叠顶点,这可能已经足够将具有相同位置的顶点组合起来。
如果没有,您可以尝试自己焊接顶点,看看是否可以解决问题。
public static void WeldVertices(Mesh aMesh, float aMaxDistDelta = 0.01f)
{
var aMaxDelta = aMaxDistDelta * aMaxDistDelta;
var verts = aMesh.vertices;
List<int> newVerts = new List<int>();
int[] map = new int[verts.Length];
// create mapping and filter duplicates.
for (int i = 0; i < verts.Length; i++)
{
var p = verts[i];
bool duplicate = false;
for (int i2 = 0; i2 < newVerts.Count; i2++)
{
int a = newVerts[i2];
if ((verts[a] - p).sqrMagnitude <= aMaxDelta)
{
map[i] = i2;
duplicate = true;
break;
}
}
if (!duplicate)
{
map[i] = newVerts.Count;
newVerts.Add(i);
}
}
// create new vertices
var verts2 = new Vector3[newVerts.Count];
for (int i = 0; i < newVerts.Count; i++)
{
int a = newVerts[i];
verts2[i] = verts[a];
}
// map the triangle to the new vertices
var tris = aMesh.triangles;
for (int i = 0; i < tris.Length; i++)
{
tris[i] = map[tris[i]];
}
aMesh.Clear();
aMesh.vertices = verts2;
aMesh.triangles = tris;
}
你正在寻找一个叫做复合碰撞器的东西。2D Tilemaps甚至有一个“用于复合”的复选框。如果你将Composite Collider 2D组件附加到你的tilemap对象上并勾选“used by composite”,它将把所有的碰撞器合并成一个大碰撞器。
话虽如此,看起来你正在使用prefabs将道路片段生成到网格上,而不是使用tilemap构建地图。你仍然可以通过在碰撞器上勾选“Used by composite”来为许多不同的GameObject使用复合碰撞器,但这比简单地在一个组件上勾选一个按钮要复杂一些,因为你将不得不配置所有的游戏对象。如果你能简化使用tilemap来制作你的道路,那么应该会更简单。
也许,你不需要改变电路,而是改变汽车碰撞系统: