Search Unity

Instantiating a 128x128 grid of cubes

Discussion in 'Editor & General Support' started by MTracerStudios, Aug 9, 2011.

  1. MTracerStudios

    MTracerStudios

    Joined:
    Aug 24, 2010
    Posts:
    118
    So, to test my grid-based server simulator, I have the logic prefab instantiate a grid of cubes, one cube for each cell on the map. I plan on changing the colors and positions of the cubes to visualize the events on the map. On a 128x128 map, this causes so much lag that unity crashes all together. I realize this is a lot of objects, but they're just cubes! Can someone tell me how to optimize a grid of cubes? It's not like that's ever been done before... (cough minecraft cough)

    Thanks,

    MTracer.
     
  2. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    Instantiating a 128x128 grid of cubes should definitely not cause Unity to Crash.

    The amount of geometry being created and initialized is very likely not your issue, but rather a logic issue where it is either looping indefinitely or stack overflowing, or any other number of issues.
    Can you show the Spawning code? And can you define 'crash' does it freeze, does it exit to desktop, does it happen in Editor or Standalone, and if you hit Editor Log in the console tab you can see what happened RIGHT before the crash to better diagnose what actually happened.
    and also this should be in Scripting not Gossip.
     
  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Minecraft doesn't use individual cubes. 16,384 objects is way too many, and will cause serious performance issues. There are a number of Minecraft threads discussing how it's done.

    --Eric
     
  4. SvenEV

    SvenEV

    Joined:
    Jul 22, 2010
    Posts:
    4
    128x128 cubes produce about 16000 drawcalls in the worst case which is definitely too many. I think it might be enough for a crash depending on your hardware. On Unity Answers you can find lots of similar questions. Most of them come to the solution: Combine objects to reduce drawcalls!
     
  5. tatoforever

    tatoforever

    Joined:
    Apr 16, 2009
    Posts:
    4,369
    If they are the same cube(being instantiated), using the same material they will all be batched and draw on the same drawcall. The crash comes from the code obviously.
     
  6. windexglow

    windexglow

    Joined:
    Jun 18, 2010
    Posts:
    378
    I can't remember if it'll cause a crash, but if each cube has collision it may be the cause.
     
  7. tatoforever

    tatoforever

    Joined:
    Apr 16, 2009
    Posts:
    4,369
    Do they also have rigidbodies? If so, they should be marked as non-static (dynamic), moving static objects is heavy.
     
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Batching doesn't work like that actually, there will still be many drawcalls, just less than 16K. In any case, that doesn't help with the overhead of having 16K separate objects being instantiated.

    --Eric
     
  9. tatoforever

    tatoforever

    Joined:
    Apr 16, 2009
    Posts:
    4,369
    I'm not trying to explain how Batching works. Just giving my advice to that specific problem.
     
  10. Micha-Stettler

    Micha-Stettler

    Joined:
    Jun 11, 2009
    Posts:
    167
    Just dont instantiate all cubes at the same time. use a coroutine.
    something like this:

    Code (csharp):
    1.  
    2.  
    3. void Start(){
    4.   StartCoroutine(FillGrid());
    5. }
    6.  
    7. IEnumerator FillGrid(){
    8.  
    9.   for(int x = 0; x < 128; x ++){
    10.       for(int y = 0; y < 128; y ++){
    11.          yield return null;
    12.          Instantiate(prefab,position,rotation);
    13.       }
    14.   }
    15.  
    16. }
    17.  
    18.  
    If you then use the same mesh and material for the cubes, a 128x128 grid should be no problem.
     
  11. niosop2

    niosop2

    Joined:
    Jul 23, 2009
    Posts:
    1,059
    I'm still not sure if it will be happy. But definitely use a coroutine for testing. That way you can watch the object and draw call count increase and get an idea of how batching is working and how much it can support before dying.

    Then try using Mesh.CombineMeshes on blocks of 200 cubes as you create them and see what the drawcall/performance difference is like.
     
  12. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You still have 16K GameObjects, which is a problem. This sort of thing really needs to have the mesh constructed on the fly, which will be orders of magnitude faster and use less memory, and it won't crash. The tradeoff being that it's harder to do, but as I mentioned, there are threads which discuss this, with code. It's a solved problem.

    --Eric
     
  13. MTracerStudios

    MTracerStudios

    Joined:
    Aug 24, 2010
    Posts:
    118
    I'll look into coding details myself, but what would the basic architecture be? Would I still instantiate all the cubes? Would I instantiate them and join them one by one into a large mesh?

    Here's my current code, I'm naming each cube by it's x/y cords so I can find it again, I want to change their colour and possible position every frame. The prefabs are simply cubes scaled 20x on the y axis. Currently it gets about half the cubes spawned after about 30 seconds, but when it gets to that point it crashes.

    Code (csharp):
    1.     IEnumerator Start ()
    2.     {
    3.         int x;
    4.         int y;
    5.         int stage = 0;
    6.        
    7.         for(x=1; x<=width;x++)
    8.         {
    9.             for (y=1;y<=length;y++)
    10.             {
    11.                 Vector3 cellLocation = new Vector3(x- (width/2), 0.0f, y -  (length/2));
    12.                 GameObject newCell;
    13.                 newCell = Instantiate(cellSprite, cellLocation, Quaternion.identity) as GameObject;
    14.            
    15.                 newCell.name = x.ToString() + "/" + y.ToString();
    16.                
    17.                 stage++;
    18.                
    19.                 if(stage >= stageLength)
    20.                 {
    21.                     yield return null;
    22.                
    23.                     stage = 0;
    24.                 }
    25.             }          
    26.         }
    27.     }
    Stage length is public and set to 64, so I'm instantiating in chunks 64 blocks long.

    What should I be doing differently?
     
  14. Ayrik

    Ayrik

    Joined:
    Aug 31, 2008
    Posts:
    430
    Does it need to be in 3D? You could just draw a pixel per cell to a 128x128 texture and display the texture on a quad or GUITexture. It would be just as easy to do and be much faster, that is, if it doesn't need to be 3D.
     
  15. MTracerStudios

    MTracerStudios

    Joined:
    Aug 24, 2010
    Posts:
    118
    Wow, I'm so retarded, thanks for that.