Search Unity

How do I update a VERY large number of GameObjects?

Discussion in 'Scripting' started by Slyder, Jul 29, 2014.

  1. Slyder

    Slyder

    Joined:
    Oct 17, 2013
    Posts:
    270
    I have 50000+ GameObjects that I need to update (tile based map generator). I need to make a pass over approximately 2800 of them one time to line up wall tiles.

    Iterating over anything 50000 times in one frame to find the walls is slow. Iterating over JUST walls and raycasting adjacent tiles to check tile type crashes editor (3-6 raycasts per tile)...Unity does not like 18000 raycasts in 1 frame as expected.

    Can anyone point me in the right direction here? I'm definitely not asking anyone to wite the code for me...I'm stumped lol

    Here's worst case scenario...each room is 15x15 = 225 tiles per room.
    Dungeon07.jpg
     
  2. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    What's your final goal? Usually with tile based games you would use some spacial partitioning to separate your world into manageable chunks.
     
  3. Slyder

    Slyder

    Joined:
    Oct 17, 2013
    Posts:
    270
    The rooms for my dungeons are stored in a branching List (to build loops). The room has no information about the walls in any room (even its own walls) if that makes sense.

    After dungeon generation, a BuildRoom function is called, which calculates the tile and tile position based on pixel colors in a BITMAP. This allows us to rapidly produce room types. Selecting the proper wall tile is trivial within ONE ROOM. The problems arise after Room generation is complete because Rooms cannot determine adjacent room wall/floor locations to account for corner pieces between rooms.

    THE GOAL IS: instead of placing the tiles correctly upon room generation, I would like to do a pass over the entire dungeon in order to select the proper wall tiles based on their adjacent tile types. This is necessary to determine where to place wall corner tiles and which type of corner to place(1 way, 2 way, 3 way, etc...). Also double sided wall tiles (floor tile on opposite sides). I would like to generate the dungeon before the player is spawned. During gameplay there will of course be some partitioning.
     
  4. Slyder

    Slyder

    Joined:
    Oct 17, 2013
    Posts:
    270
    One possibility that might work is to spawn tile placeholders for walls. These placeholders would need a Script attached to them that invokes co-routine (so that it runs after ALL wall placeholders are instantiated). In this manner, one co-routine is called on each wall tile, instead of attempting to call all of them from a single Coroutine in the MapGenerator script.

    The co-routine would check adjacent walls/tiles through raycast and swap the placeholder for the proper wall tile. I would imagine that Unity would have some sort of co-routine handling so that it's not blasting my CPU with 18000 raycast attempts in 1 frame and instead spreading them out...
     
  5. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    Would you not be better off scanning the bitmap plan for this information, as it sounds like the bitmap will contain enough information to work this out without having to use raycasts?
     
  6. Slyder

    Slyder

    Joined:
    Oct 17, 2013
    Posts:
    270
    The bitmaps are only maps of one room so the "wall" in one room has no way of knowing whats adjacent to it in the adjacent room. This is only a problem when trying to make open corridor pieces that do not have doors or end walls (think a long hallway)

    The only purpose the bitmap serves is to get a pixels color and spawn the appropriate tile based on color in the proper position.

    I've also tried generating a dungeon bitmap by piecing together room bitmaps, but 50000+ iterations of GetPixel and SetPixel through an image isn't exactly fast. Basically it locks up the editor because it's too much happening in a single frame.
     
    Last edited: Jul 29, 2014
  7. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    OK but if you make a larger bitmap, or boolean array of the actual map could you not use this to work out the corners and walls?
     
  8. Slyder

    Slyder

    Joined:
    Oct 17, 2013
    Posts:
    270
    Yes, this would work perfectly and was what I was working on all night last night. I generate a dungeon map by piecing together the room maps. This doesn't seem any faster, and Texture2D.Apply() is a very expensive operation.

    Boolean Array may be faster, I'm not sure how long 50000 iterations over a boolean array would take.

    I would generate at most a 255x255 Array or dungeon bitmap
     
  9. der_r

    der_r

    Joined:
    Mar 30, 2014
    Posts:
    259
    Do you have to do that each frame? How about putting the algorithm into a co-routine and break it up using yield return WaitForSeconds(..) to give the engine some breathing room.

    Placing wall tiles doesn't sound like something you have to do each frame.
     
  10. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    I just skimmed this, so forgive me for inaccuracy. But if you need a lot of processing done I would just spawn a coroutine and do partial processing per frame.
     
  11. Slyder

    Slyder

    Joined:
    Oct 17, 2013
    Posts:
    270
    This is the next thing I was going to try but ran out of time last night.
     
  12. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    Maybe I have this wrong but won't you only need to do this once as it's when you are building the map?
     
  13. Slyder

    Slyder

    Joined:
    Oct 17, 2013
    Posts:
    270
    Yes, I will only need to do it once. I just need to break the algorithm up in some way so that it is not trying to run everything in a single frame.

    co-routine and yield seems to be the answer. I'll have to test when I get home.
     
  14. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    If you have the room layouts as bitmaps then you only need to scan their edges/boundaries, would this not reduce the amount of work needed?
     
  15. Slyder

    Slyder

    Joined:
    Oct 17, 2013
    Posts:
    270
    Room walls are not always on the boundaries :p...a room doesn't always occupy the full space allowed for a room.
     
  16. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    I would still be tempted to look at 'drawing' the layout into an array and then parsing the array for the wall types you will need, this should be way faster than raycasts. And in the process of drawing the layout you could record the boundaries and therefore limit your wall/corner testing to those areas.
     
  17. Slyder

    Slyder

    Joined:
    Oct 17, 2013
    Posts:
    270
    yeah...switching to an array would probably be better. I wanted to do a bitmap because it's easier to visualize (I can produce an output file) and I can send the bitmap directly to the RoomGenerator to build the entire dungeon in one pass.
     
  18. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    I think you need to look into a technique such as geographic grid registration. Similar in concept to a quad tree, but with no depth. Using this spatial system it would be a little more trivial because you could keep track of where processing starts and ends and spread the processing out across multiple frames.
     
  19. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
  20. Dustin-Horne

    Dustin-Horne

    Joined:
    Apr 4, 2013
    Posts:
    4,568
    GGR essentially functions as a multidimensional array. The only difference is that each cell has a reference to its neighboring cells. In this case, a whole series of tiles could belong to a single cell... for instance he could devide the world into 3 x 3 cells, so the tiles would be divided up between them. Then each frame he could process one or two cells worth or tiles to spread the workload.
     
  21. Slyder

    Slyder

    Joined:
    Oct 17, 2013
    Posts:
    270
    Well...it turns out I was two yield statements away from a sub .5s full dungeon generation into a bitmap :D
     
  22. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    coroutines...a programmers best friend ;)