Search Unity

Procedural mesh with fixed sized arrays

Discussion in 'Scripting' started by Mistale, Oct 31, 2014.

  1. Mistale

    Mistale

    Joined:
    Apr 18, 2012
    Posts:
    173
    Hi,

    When creating meshes from scripts, I always use Mesh.vertices etc to assign arrays to the new mesh.
    A big problem of mine is that it means I have to create arrays of a suitable length for the current mesh in order to assign them.

    This leads to GC allocations during runtime, since I never use those arrays again.
    I do not have the luxury of having the same number of vertices in all meshes, instead all meshes are unique and there are hundreds of them being generated at once.

    Is it possible in any way to set vertices, normals, uvs and triangles from arrays that have a larger size than necessary?
    That would allow me to re-use a few 65k arrays for all meshes.

    So in short, can you somehow specify another length for attributes than what arrays have when assigning them to runtime meshes?

    I thought this would be part of 4.6 since there was a lot of talk about optimizing runtime meshes for the new GUI, but that seems to have been limited to meshes for the Canvas.

    If this functionality is not present, I would love to hear opinions from Unity representatives regarding the possibility to include it in the near future (in 5.0 for example).

    What I need is basically extra methods in the form Mesh.SetVertices(Vector3 [] array, int vertexCount), but for all assignable mesh attributes.
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    That functionality does not exist for the Mesh class.

    --Eric
     
  3. Mistale

    Mistale

    Joined:
    Apr 18, 2012
    Posts:
    173
    @Eric5h5 : Thank you for answering, too bad it's not available (yet). I'm having a lot of issues with multiple large arrays being put in the LOH (Large Object Heap) which then leads to memory fragmentation / overuse on iOS due to this.
     
  4. akderebur

    akderebur

    Joined:
    Apr 21, 2013
    Posts:
    18
    Hi. I couldn't understand this part.
    What do you mean by never use again? For example in a situation like below isn't the array used all the time by the mesh or am I missing something?

    Code (CSharp):
    1. Mesh mesh = new Mesh();
    2. mesh.vertices = new Vector3[]{new Vector3(0,0,0), new Vector3(0,0,1)};
    Can you give an example please?
     
  5. Mistale

    Mistale

    Joined:
    Apr 18, 2012
    Posts:
    173
    I don't think the actual C# arrays are used internally after you have supplied them to mesh.vertices etc, that would be very fragile since you could change the values in your arrays and Unity would have to catch that and react to it.

    I'm not at my computer at the moment, so I can't double check.
    I've always assumed that the arrays are copied into C++ land for further processing.
    That would explain why you always get a new array if you read back mesh.vertices at a later time.

    *If* my assumption is correct, that means that each time you create new arrays to fit the vertex count of a new mesh, those arrays are just created, copied by Unity and then thrown away leading to memory issues if there are lots of them.

    If it was possible to use the same arrays for setting up any mesh regardless of vertexcount, you could have those arrays set to hold 64k values and store them as static members, meaning they would only use memory once, when they are declared.
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You could allocate the array to the max size you're going to use, and leave the unused vertices as Vector3.zero.

    --Eric
     
  7. Mistale

    Mistale

    Joined:
    Apr 18, 2012
    Posts:
    173
    Interesting! I do need to set the size to 64k in that case, since we're parsing collada files of unknown size.
    Do you know what would happen if you pass 'ordinary' triangle arrays, meaning arrays of correct size and that dont use the extra vertices?
     
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Nothing will happen, if you mean would there be any errors.

    --Eric
     
  9. Mistale

    Mistale

    Joined:
    Apr 18, 2012
    Posts:
    173
    I tried the fixed array approach, having arrays of size 65000 for vertices, uv1 and uv2. The arrays were padded with zero-values above the "real" vertex count of the current mesh.

    Before changing to this, I used pooled lists of size 65000 for the attributes (using .ToArray() when assigning mesh attributes).

    When profiling my custom meshcombiner with the pooled list approach, 899 combined meshes took 350 ms, and allocated 9.7 mb of data. Most of the meshes had pretty moderate vertex count.

    When profiling the fixed array approach, 899 combined meshes took 1450 ms, and allocated 3.5 mb of data (I still used lists for the triangles). Most of the time was spent in Mesh.RecalculateNormals() which seemed to have a hard time with the added amount of vertices, even though they were degenerate.

    However, immediately after checking the profiler for the fixed array approach, the Editor froze completely and I had to shut it down.
    This happened repeatedly, and makes me think that 899 x 3 arrays of 65000 elements is perhaps too much to assign to procedural meshes even if most values are never used.

    Any other ideas?