Search Unity

extreme object pooling for large maps (iOS)

Discussion in 'Scripting' started by nachobeard, Jul 13, 2014.

  1. nachobeard

    nachobeard

    Joined:
    May 7, 2013
    Posts:
    47
    Hi,

    I'm making a 2d platformer for iOS where the levels are totally seamless, so you can play the whole game from start to finish without reaching the end of the level or any similar artificial barriers.

    My question is, how to place a large amount of enemies in a single large map without wasting memory.

    Suppose there's 3000 enemies in the game, which I've painstakingly placed using the unity editor. When I press "play" on the editor all 3000 enemies in the game are spawned, so even if I use some pooling strategy it won't be of much use because all 3000 enemy instances will be created by the editor at once - and they'll never get reused because there's no more enemies left in the game :/

    I could deactivate enemies which are too far from the main character and activate them once they come close enough, but that seems like a huge memory waste, because all 3000 enemies still exist in memory even if most of them are inactive. So that's no use.

    Maybe instead of having 3000 enemies directly on the scene I could have 3000 "spawner" objects (which would presumably use very little memory) instead of the 3000 enemies themselves. The spawner objects are inactive, but when the main character gets relatively close to a spawner, it gets activated so it'll create the specified enemy.

    Another more extreme alternative would be to code up something which will look at my unity scene, then store (in an xml or something) all the enemies that are present in the scene together with all their attributes. Then when the game is running there would be a script to spawn the enemies in the xml one by one as the player gets close enough to them.

    I'm just not sure which alternative is the best, and am hoping to find someone who knows better!

    Alternatively, if anyone knows of a plugin that can do this, I'd be delighted to hear, of course :)

    Thanks
    -nacho
     
    Last edited: Jul 13, 2014
  2. jotapeh_

    jotapeh_

    Joined:
    Nov 16, 2012
    Posts:
    45
    Having tackled similar problems..

    Deactivating enemies that are a bit of a distance away from the main camera is probably your best bet. This can be done simply by loading all enemies into a List<GameObject> at start. A simple script can check for proximity every x unit of time. In my experience this works very well even at thousands of game objects. This is likely the most viable solution.

    If that still doesn't work, consider writing an editor script which compiles the locations of all enemies into a file. Then another script can load the positions and only spawn enemies once the camera is near enough. This suffers from the same memory problems however if the player is able to run around without engaging the enemies, leaving them activated but alive. It's also worth noting that Instantiate() is a bit of a costly call and can cause noticeable stutter.

    Good luck!
     
  3. nachobeard

    nachobeard

    Joined:
    May 7, 2013
    Posts:
    47
    hey jotapeh, many thanks for your answer.

    I'll try the approaches you mentioned, the first one seems particularly easy to implement.

    I assume you've tried this on mobile, right?

    many thanks!
     
  4. jotapeh_

    jotapeh_

    Joined:
    Nov 16, 2012
    Posts:
    45
    Yes, on iOS and Windows Phone. Works well on both.
     
    nachobeard likes this.
  5. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    You could also consider segmenting your level. If you divide it into 36 section (6 x 6) each of these could have just a few enemies. These could be placed into different scenes (yes, you'd need one scene for every section) and the scene loaded additively when the player gets to a particular range. If you name your scenes intelligently (e.g. "Level_Enemies_2x3") you can load the scenes dynamically, and until they're loaded they take ZERO memory. (If you have Pro, you can use LoadLevelAddtiveAsync so there's no noticeable stuttering either) Better yet, their art assets won't be preloaded either. (I'm using this currently for a 2D game with lots of huge, beautiful landscapes - this technique has been utterly vital to making the game run on mobile at all)

    One further trick: If you want to edit the placement of your stuff while in the main scene, use a prefab. Create "Level_Section_1x1" scene, in it place "Prefab_Section_1x1". When you want to edit it, drop the prefab into your main scene, make your changes, hit apply, delete the prefab from your main scene.
     
  6. Apparaten_

    Apparaten_

    Joined:
    Jul 9, 2013
    Posts:
    45
    Well, as long as you don't have to see all the 3000 enemies at once, you can pool ex. 100 and activate/deactivate them 30 times at a list of 3000 positions :)
     
  7. nachobeard

    nachobeard

    Joined:
    May 7, 2013
    Posts:
    47
    excellent, many thanks to all!