How to avoid frequent INSTANTIATING DESTROYING objects (=low FPS), in an iOS game?

I’m making an iOS board game.
In this game, collectibles (I’ve got 4 different types of them) are instantiated at random positions every 4” and using my character (that moves on the board) I collect ( destroy) the collectibles.

I was having a HUGE framerate problem, caused mainly by the way I managed the board (I was checking which board tiles are empty and instantiating a collectible randomly on one of them, using GameObject.FindWithTag…). After getting lots and lots of help by the community, I corrected the way these things are managed, but I’m still having low framerate (better than before, but still unacceptable).

I just learned that this, is almost definitely caused, by the frequent instantiating and destroying of objects, which kills the iphone performance. What’s more, this is an “endless mode” type of game, where one can play for many many minutes in this same level and after say 10’ there can be 100 collectibles that have been well…collected (thus destroyed). After about a minute of playing, the game is almost frozen… Oh and of course, some sounds don’t play (because of GC I suppose?)

The board has 48 tiles and at maximum it can have about 10-15 collectibles of each type on-screen (due to the fact that what kind of collectible will be instantiated is random and is done from a built-in Array with these 4 objects).

What would be a good approach to doing what I want, without instantiating/destroying the collectibles?

I’ve thought of creating 15 collectibles of each type off camera at function Start and having them moved (instantly) at random tiles every 4’’ and being moved off camera (instantly again) whenever my character collects them, but haven’t figured out how to select a random collectible between the ones that are still off board.

Hi,

I was thinking of doing something like this for my game, setting the mesh renderer to false for anything which isn’t on the screen and when it is, then turn it on. It’s just an idea I had for my project so it probably won’t work, but worth a shot if nothing else is working.

Thanks

Dan.

You need pooling.

You need an array of objects, even more objects than can be used, and set them to inactive. (This is good to do with bullets, aliens, asteroids, etc…)

When you place one, iterate thru the array and set the first object you find that is inactive to active, place it in the game, and break your iteration loop. When an object is collected, account for it and increment the collection counter and then set it to inactive and it’s back in your pool to use again. You can choose to move these to an offscreen location or not. Heck - they’re deactivated.

If you can’t imagine how many of each type (say a max of a total of 100 objects, but they could be of 4 types, so you’d need 100*4=400 objects to be safe…), then could you make an object that could appear as any of the 4? Take it out of the pool, set it’s type. (CollectionType = Cherry), activate it, place it… etc.

Make sense?

I’ll try to do something according to your suggestion. Thanks Little Angel.

@greensquidsolutions: thank you Dan, I guess activate/deactivate as LittleAngel suggests, sounds better.

no worries, it gives me an idea on how to approach it when I come to do something like this :slight_smile:

Thanks

Dan.

I use the following script, attached to an empty game object:

var popSoundAtSpawn: GameObject; //the sound that plays when a token is spawned
var spawnObjects : GameObject[ ];// this is the Array comprised of tokens that will be randomly spawned
var tilesArray : GameObject[ ];// this is the Array comprised of all squares of the board
var tokensPool : GameObject[ ];//this is the Array comprised of 15 tokens that at maximum will be on board at the same time
var spawningRate: float= 3.3; // every spawningRate seconds, one token will be moved on board
var delayBeforeSpawningBegins: float =2;// when the level begins, it will wait 2" before it starts spawning tokens
var emptySquares: int;
var spawnSuccessful: boolean;
var tokensSpawned: int=0;

function Awake(){
InvokeRepeating(“Spawn”, delayBeforeSpawningBegins, spawningRate); // make spawn a token every “spawningRate” seconds
}

function Spawn(){
randomTileNumber = Random.Range(0,tilesArray.length); //this will choose a random tile of the board
randomTokenNumber = Random.Range(0,tokensPool.length); // this will choose a random token from the tokens Pool
var spawnSuccessful = false;
while (spawnSuccessful == false (tokensSpawned-characterScript.tokensSwallowed)<47)) {// this makes sure that the tokens spawned minus the ones swallowed by my character are less or equal to my available board tiles, which are 48 (in total) minus 1 that my character occupies = 47. So the while’s escape condition, will be met when the board is full of tokens
var placeToSpawn: GameObject = tilesArray[randomTileNumber]; //the position of one of the randomly selected board tiles. In that position will the token be spawned
var spawnedToken: GameObject = tokensPool[randomTokenNumber]; // this will pick randomly, one of the tokensPool Array’s contents
if (placeToSpawn.tag == “EmptyTile” spawnedToken.active == false){ // this checks if the selected tile is empty and if the selected token is one of the deactivated tokens that are still off-board and have not been moved on it.
iTween.MoveTo(spawnedToken,{“x” : placeToSpawn.transform.position.x, “y” : 0, “z” : placeToSpawn.transform.position.z,“time”:0}); //this will move the token instantly, on the randomly selected empty tile’s position
spawnedToken.active = true; //the token will be activated
tokensSpawned ++; // the number of instantiated tokens will be increased
Instantiate(popSoundAtSpawn); // the spawning “pop” sound will be played
spawnSuccessful = true; // the while’s escape condition will be met
}
}
}

What happens, is when I hit play, sometimes 5, sometimes 10 (at best) collectibles are activated and spawned in random positions (as expected) and Unity freezes. Am I getting into an infinite loop? Isn’t this script a good way to have the token prefbs spawned and removed from the board?
Even if i simplify the “while” line like this:

while (spawnSuccessful == false ) {

I get the same freezing after 5-10 spawns problem. It seems like Unity freezes when it tries to randomly pick a token from the tokensPool, that has already been picked-spawned and is already on the board. I would expect it not to try to pick an already spawned token though, as I use:

spawnedToken.active == false

in the “if” statement.

Actually the problem was that I had:

randomTileNumber = Random.Range(0,tilesArray.length); //this will choose a random tile of the board
randomTokenNumber = Random.Range(0,tokensPool.length); // this will choose a random token from the tokens Pool

out of the while loop.
It caused the engine to occasionally try to pick a token that had already been picked and that hanged it.
Putting them inside the “while” (thanks to Marowi’s help here), solved the problem.