在运行时修改顶点

时间:2018-03-05 06:41:31

标签: c# unity3d mesh

对于我在Unity中运行时使用的一小组自定义地形工具,我需要能够“绘制”地形区域以提升和降低它。

要做到这一点,我有这个功能:

public void PaintRaise(Vector3 center, float radius, float power) {
    Mesh mesh = this.gameObject.GetComponent<MeshFilter>().sharedMesh;
    Vector3[] verts = new Vector3[mesh.vertices.Length];

    for (int i = 0; i < mesh.vertices.Length; ++i) {
        // method for getting distance, faster then Vector3.Distance
        var heading = mesh.vertices[i] - center;
        var distance = heading.magnitude;
        var direction = heading / distance;
        if (heading.sqrMagnitude < radius * radius) {
            verts[i] = new Vector3(
                mesh.vertices[i].x,
                mesh.vertices[i].y + power,
                mesh.vertices[i].z);
        } else {
            verts[i] = mesh.vertices[i];
        }

    }
    mesh.vertices = verts;
}

理论上,它应该可以完美地应用于带有网格的GameObject,它确实可以!但不幸的是,它非常非常缓慢。即使使用improved距离查找方法,处理半径为5个单位也需要大约10秒钟。

它在编辑器和编译版本中运行速度都很慢。

enter image description here

正如您所看到的,探查器显示调用PaintRaise函数的Update()函数需要大约13秒来执行单帧,其中大部分是garabage收集器!

为什么它运行缓慢,如何加快速度(理想情况下需要几毫秒才能执行)?

修改

启用深度分析会让它更加混乱!为什么由于GC而使网格顶点需要13秒?

enter image description here

1 个答案:

答案 0 :(得分:1)

在做了一些研究后,我发现顶点是not actually a variable,就像它看起来一样。

  

新的SetVertices / SetIndices / SetUVs /方法有几个原因。首先,旧的顶点属性不是变量。这个事实让许多用户感到困惑。这是一个财产。实际上有一个get方法和一个set方法,但用法看起来就像一个变量。

     

最不理解的是getter不会返回对内部数组的引用,而是返回一个副本。这是必要的,因为实际的顶点数据存储在Unity的本机C ++端。

更改我的函数以使用Get()和Set()消除了使用vertices属性创建的额外垃圾收集,并使其运行黄油顺利。

public void PaintRaise(Vector3 center, float radius, float power) {
    Vector3 localPoint = transform.InverseTransformPoint(center);
    Mesh mesh = this.gameObject.GetComponent<MeshFilter>().sharedMesh;
    List<Vector3> verts = new List<Vector3>(); 
    mesh.GetVertices(verts);

    for (int i = 0; i < verts.Count; ++i) {
        var heading = verts[i] - center;
        var distance = heading.magnitude;
        var direction = heading / distance;
        if (heading.sqrMagnitude < radius * radius) {
            verts[i] = new Vector3(
                verts[i].x,
                verts[i].y + power,
                verts[i].z);
        }
    }
    mesh.SetVertices(verts);
}