【问题标题】:Accessing mesh vertices performance issue访问网格顶点性能问题
【发布时间】:2018-08-15 08:12:42
【问题描述】:

这段代码运行缓慢(执行循环大约需要 250 毫秒)

mesh.triangles.Length 为 8700。

我在最新的 Unity 平台(版本 2018.2.3)上使用 c#。

我怀疑这是因为每次迭代我都在两个数组之间切换,即。我从三角形中取一个值,然后查找它的顶点元素。

mesh.triangles 是一个整数数组。 mesh.vertices 是 Vector3 的数组。


while (j < mesh.triangles.Length)  
{

    m_Particles [currentParticlePos].position =  vertices[mesh.triangles[j]];   

    // allocate a particle to every 3rd vertex position.
    j = j + 3;
    currentParticlePos++;
}

【问题讨论】:

  • 您如何对代码进行基准测试/分析,您是否 100% 确定 仅此循环 需要 250 毫秒?
  • 我正在使用一个简单的秒表类并围绕循环代码开始/停止。实际上没有什么其他东西在运行,就像将粒子分配到顶点的简单实现一样。我按照 Unity 的要求在循环的任一侧获取/设置粒子,但我之前使用过该技术没有任何问题。

标签: c# unity3d mesh vertices


【解决方案1】:

在此处手动强制进行一些微优化可能会对您有所帮助。

首先,mesh.triangles 是一个属性,有自己的 getter 和 setter。你会在每个循环中获得轻微的性能影响。因此,让我们在循环开始之前将该地址存储为局部变量。

其次,mesh.triangles.Length 的值始终相同。所以让我们将它存储在一个局部变量中,而不是在每个循环中调用该属性。

接着,您的代码使用vertices [ ],而您的问题是mesh.vertices [ ]。如果您在每个循环中检查mesh.vertices [ ],您也需要在本地存储它。

现在,根据编译器的不同,可能已经处理了以下微优化。因此,您必须使用计时技术来验证这是否值得。说了这么多,我们现在来看代码:

int [ ] triangles = mesh.triangles;
int length= triangles.Length;
int [ ] vertices = mesh.vertices;

while (j < length)  
{
  m_Particles [ currentParticlePos++ ].position = vertices [ triangles [ j ] ];   
  // allocate a particle to every 3rd vertex position.
  j = j + 3;
}

附带说明,虽然它现在对您没有帮助,但 C#7.x 引入了 ref struct 和一些其他有用的功能,这些功能将加快访问速度,将所有内容保留在堆栈中。 This article 读起来很有趣,当 Unity 赶上来时会很有用。

编辑:如果您的网格没有改变(这很可能),那么您可以预定义您需要的确切顶点的数组。然后你也只需要增加一个变量。这是一个极端的微观优化。这可能有助于 CPU 预取...(在此处插入耸肩表情符号)。

// The mesh. Assigned as you see fit.
Mesh mesh;

// The length of the new vertices array, holding every third vertex of a triangle.
int length = 0; 

// The new vertices array holding every third vertex.
Vector3 [ ] vertices;

void Start ( )
{
    int [ ] triangles = mesh.triangles;
    length = triangles.Length / 3;
    vertices = new Vector3 [ length ];

    for ( int count = 0; count < length; count++ )
        vertices [ count ] = mesh.vertices [ triangles [ count * 3 ] ] ;
}

private void Update ( )
{
    int j = 0;
    while ( j < length )
    {
        m_Particles [ j ].position = vertices [ j++ ];
    }
}

【讨论】:

    【解决方案2】:

    您正在使用mesh,但您没有修改任何值。在这种情况下,您可以考虑改用sharedMesh。在您的特定情况下,mesh 的问题在于,mesh 创建了一个副本并将其返回。使用sharedMesh,您可以从另一个网格实例的额外开销中解脱出来。请查看meshsharedMesh 的文档以获取更多信息。

    【讨论】:

      【解决方案3】:

      循环运行不慢;此循环、Unity 引擎和您可能拥有或不拥有的任何其他资产需要 250 毫秒。

      【讨论】:

      • 好的,那么有没有另一种方法来实现它以实现更快的相同结果?
      • 很遗憾没有,但是如果您希望您的游戏/应用程序运行得更快,请尝试优化您使用的资产并使用 LOD 等优化技术。
      • 好的,谢谢 - 我将拆分多个帧以减少对帧的影响。现在我知道我的代码是正确的。
      【解决方案4】:

      我也遇到过这个问题。如果可能,您应该按照三角形数组指定它们的顺序预先生成一个顶点数组。否则,您将访问内存中的随机位置,这确实会破坏性能。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-21
        • 1970-01-01
        • 2013-07-04
        • 1970-01-01
        • 2022-11-29
        相关资源
        最近更新 更多