简化道路系统的碰撞网格?

Phi*_*sen 6 c# unity-game-engine

给定 Unity 中 3d 中基于图块的道路或人行道系统,如图所示,我看到刚体在接缝处移动的小凸起(即使对于相同的垂直位置和比例,以及为每个图块使用框碰撞器时)。有没有一种好方法,例如将碰撞网格组合成一个超级简化和全平面的网格?我没有运气,例如导出为对象(无论是使用我的网格简化器),因为在重新导入和摆脱单个盒子碰撞器时明显的迷你颠簸仍然存在。我的要求不是它必须是实时的(尽管如果没有缺点,那会有点加分)。谢谢!

道路系统

Plu*_*uto 5

您可以尝试使用Mesh.CombineMeshes将所有小对撞机制作成一个大对撞机。

[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;
    }
}
Run Code Online (Sandbox Code Playgroud)

需要注意的一件事:生成的组合网格在世界空间坐标中,因此如果附加到的游戏对象有任何变换更改,它们也将被应用。

如果您启用了 MeshCollider -> Cooking Options -> Weld Colocated Vertices,这可能就足够了,这应该组合具有相同位置的顶点。

如果没有,您可以尝试自己焊接顶点,看看是否能解决问题。

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;                
}
Run Code Online (Sandbox Code Playgroud)


这是一个示例(之前和之后): 6 个以上有明显间隙的对撞机,1 个以下没有间隙的对撞机。

在此处输入图片说明


Eri*_*low 0

您正在寻找一种称为“复合碰撞器”的东西。2D Tilemap 甚至有一个“由 Composite 使用”复选框。如果您将复合碰撞器 2D 组件附加到图块地图对象并勾选“由复合使用”,它将把所有碰撞器组合成一个大型碰撞器。

话虽如此,看起来您正在使用预制件在网格上生成道路片段,而不是使用图块地图构建地图。您仍然可以通过在碰撞器上勾选“由复合使用”来将复合碰撞器用于一堆不同的游戏对象,但这比简单地在一个组件上勾选按钮要复杂一些,因为您必须配置所有游戏对象。如果您可以简化为在道路上使用瓷砖地图,那么事情应该会简单得多。