Using a pool of objects that will be spawned ONCAMERA and removed OFFCAMERA instead of INSTANTIATE & DESTROY (iOS)

I want to use a pool of prefabs that will be randomly spawned on (random) squares of my board every 4 and collected (and removed from the board) by my character.

The board has 48 tiles, one of which is constantly occupied by my character that moves on it. This leaves 47 tiles available for the spawned tokens to occupy.

My initial approach was instantiating and destroying these prefabs, which resulted in extremely low fps. This way I learned that this practice (frequent instantiating & destroying) is to be avoided in iOS games.

After asking lots of questions and posting here and in the Forum, what Im trying to do now, is use a pool of deactivated prefabs that will be activated when needed, instantly moved to a random tile on board (as If I instantiated them) and deactivated and removed from the board (as If I destroyed them), when my character collects them.

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 47 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? Isnt 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.

I haven't tested this locally to confirm, but at a glance it seems that it would break as soon as it randomly selected an occupied tile, or a token that was already spawned.

This bit here:

var placeToSpawn: GameObject = tilesArray[randomTileNumber];
var spawnedToken: GameObject = tokensPool[randomTokenNumber];

is occurring inside the `while` loop. If either `randomTileNumber` or `randomTokenNumber` are inappropriate (according to the following ifcheck), then it will hang infinitely. You can fix this by putting the Random.Range inside the `while` loop.

There might be better approaches to this scenario, but this should fix your immediate problem - it's 2am here and my creative thinking is a bit zapped for the day.

Let me know if you have any troubles or questions. Cheers.