Search Unity

Memory problems with procedurally generated meshes

Discussion in 'Editor & General Support' started by stevosaurus, Aug 25, 2010.

  1. stevosaurus

    stevosaurus

    Joined:
    Aug 25, 2010
    Posts:
    3
    Hello!

    I am new to Unity and me and have run into a problem that I can't solve.

    I am generating my games terrain procedurally, and storing the meshes for the terrain in several different game objects. I don't use one big mesh because I want to be able to quickly update one part of the mesh at runtime.

    I am reusing gameobjects to hold new terrain as you move through the world and I repopulate their meshes with this code:

    Code (csharp):
    1.  
    2. Mesh mesh = GetComponent<MeshFilter>().mesh;        
    3. mesh.Clear();
    4.        
    5. mesh.vertices = vertArr;
    6. mesh.normals = normArr;
    7. mesh.uv = texArr;
    8. mesh.triangles = indArr;
    9.  
    10. mesh.RecalculateNormals();
    11. mesh.RecalculateBounds();
    12.  
    This works well, but uses more memory every time I redo the mesh. Looking at the stats window it seems that my VBO total and the ram associated with it is probably the culprit. Looking at the profiler, my mesh number is always the same but the mesh memory increases with the VBO memory.

    Is there anyway to get around this? Is assigning mesh.vertices several times just a bad idea?

    Thanks for your help!
     
  2. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Hi, welcome to the forum!

    There are a number of places in mesh generation code that can allocate memory including some internal properties. You can't do much about the internal stuff, but you can reuse already allocated arrays for vertices, etc. In general, the allocated memory isn't a big problem, since it can be reclaimed (although the garbage collection process can be a CPU spike).
     
  3. stevosaurus

    stevosaurus

    Joined:
    Aug 25, 2010
    Posts:
    3
    Thanks for your response!

    I am reusing all of the arrays I assign the mesh. I wouldn't mind Unity grabbing up memory when assigning the arrays if the memory was eventually reclaimed.

    The memory never seems to be reclaimed though, at the start of the game I am using about 150mb, but if I walk around the world the memory used just keeps increasing (after a few minutes it can be 500mb+).

    Here is some more details about how I am doing things:
    Code (csharp):
    1.  
    2. /* compute num of vertices and tris I need */
    3. GetCount();
    4.  
    5. /* create arrays */
    6. vertArr = new Vector3[pointCount];
    7. texArr = new Vector2[pointCount];
    8. normArr = new Vector3[pointCount];
    9. indArr = new int[indexCount];
    10.  
    11. /*fill the arrays */
    12. FillArrays();
    13.  
    14. myMesh.Clear();
    15. myMesh.vertices = vertArr;
    16. myMesh.normals = normArr;
    17. myMesh.uv = texArr;
    18. myMesh.triangles = indArr;
    19.  
    20.  
    21. vertArr = null;
    22. texArr = null;
    23. normArr = null;
    24. indArr = null;
    25.  
    If I do not assign the new arrays to the mesh (but still allocate and fill the arrays) then I do not see the memory leak.

    I have tried everything I can think of, including destroying the mesh and then creating a new mesh, and manually calling Resources.UnloadUnusedAssets() after mesh updates but nothing seems to work. In the procedural examples they go through the same processes I do, but they seem to be using the same number of vertices in the new array. In my setup the numbers of vertices will be changing all the time.

    I am really liking the engine so far, but this problem is very frustrating :(

    Anyways, thanks for your help!
    -Steven
     
  4. MikeHergaarden

    MikeHergaarden

    Joined:
    Mar 9, 2008
    Posts:
    1,027
    I'm noticing the same behavior in Cubelands. I really hope this has been fixed in 3.0...

    Trying to create a example scene in 2.6 to showcase this and then test 3.0
     
  5. MikeHergaarden

    MikeHergaarden

    Joined:
    Mar 9, 2008
    Posts:
    1,027
    Bah, no change at all in Unity 3. You can crash Unity on command using this leak.
    Reported case: 373918

    Edit: Phew, this seems to be by design! When creating custom meshes you need to manually call destroy on the .mesh object. Simply destroying its meshrenderer and meshfilter (and gameobject) doesn't work. This makes sense.
     
  6. TwiiK

    TwiiK

    Joined:
    Oct 23, 2007
    Posts:
    1,729
    Are you saying you have solved this?

    I thought I tried destroying and cleaning up more or less everything as well as calling garbage collection manually etc. etc. etc. :)
     
  7. MikeHergaarden

    MikeHergaarden

    Joined:
    Mar 9, 2008
    Posts:
    1,027
    Yep, it's solved! In my repro project it added 50mb in 25 seconds. It doesn't do that when explicitly calling Destroy on the mesh.

    Code (csharp):
    1. Destroy(go.GetComponent<MeshFilter>().mesh);
    2. Destroy(go);
     
    cyber_shawn likes this.
  8. TwiiK

    TwiiK

    Joined:
    Oct 23, 2007
    Posts:
    1,729
    That sounds awesome.

    Can't wait to give this a try when I get home from work. :)
     
  9. stevosaurus

    stevosaurus

    Joined:
    Aug 25, 2010
    Posts:
    3
    I had thought we tried this as well. But I will give it another try!

    Thanks for your response, our games are very similar (minecraft?!) so it's no wonder you were seeing the same problems. Our mc clone is pretty pathetic at the moment though :p

    Cubeland looks awesome, would love to play it!
     
  10. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    I'm also creating meshes at runtime, and after reading this thread I'm wondering if I'm doing it right.

    As far as I can tell, simply assigning new data to a mesh (even when the number of vertices or triangles changes) does not cause a memory leak; it's only if you destroy the corresponding game object without also destroying the mesh that the mesh is leaked. Is this correct?
     
  11. TwiiK

    TwiiK

    Joined:
    Oct 23, 2007
    Posts:
    1,729
    I could not get this to work. Destroying the mesh object before the game object made no difference.

    Would you care to post or send me your repro project as I'm obviously doing things very inefficiently here and it may be other things increasing the ram in my case.

    I'm currently combining my meshes more or less like they do in this example: http://unity3d.com/support/documentation/ScriptReference/Mesh.CombineMeshes.html

    @Jessy, I don't think this has anything to do with creating or destroying meshes at runtime actually because I can instantiate and destroy an infinite number of meshes without it affecting my ram usage.

    It's only when I try to store or combine the meshes that things start to go haywire.
     
  12. Tzan

    Tzan

    Joined:
    Apr 5, 2009
    Posts:
    736
    On that crappy example script is the lines:

    renderer.mesh = new Mesh();
    renderer.mesh.CombineMeshes (combine);


    Dont create a new mesh();

    Your parent object has a MeshFilter already.
    Then CombineMeshes makes its own new mesh and puts it into the parent.mf.mesh.

    That new Mesh()command is a problem spot.
    Just change that line and see how it works. Comment it out.

    Yes I'm also making a blocky game, but I started mine in Jan 2008, so uhm... minecraft copied me :)

    Old thread, I already posted the important part above.
    http://forum.unity3d.com/viewtopic.php?p=384330&highlight=#384330

    ---

    Also using the mesh from CombineMeshes() doesnt seem to work when used as a mesh collider. Yes Boxes are more efficient for some things but it should work.

    My bug is still open
    http://intra.unity3d.com/fogbugz/default.asp?364060_rrrpcgrt