Search code examples
c#unity-game-enginegameobject

How to Move disabled gameObjects from one list to another?


I'm been making an endless runner game. I have a set of tiles (4 atm) which I spawn randomly. For optimization purposes I decided instead of instantiating and destroying game objects once the player run though it do disable them and once a when a tile is needed to spawn from the deactivated tiles. I made two lists active and deactivate which will do the above scenario. I managed to disable them but I don't know how to add them to the disable list and spawn them when. needed. How can I achieve it.

Here's the code and what I did so far.

TileManager.cs

void Update () 
    {

            //Vector3 offset = new Vector3(0f, 0f, Time.time * speed);
        //GameObject go;
        //go.transform.SetParent(transform);
            if (playerTransform.position.z - safeZone > (spawnZ - amtOfTilesOnScreen * tileLength))
            {
                SpawnTile();
                DeleteTile();
            }

    }

    private void DeleteTile()
    {
        //Destroy(activeTiles[0]);
        activeTiles[0].SetActive(false);
        activeTiles.RemoveAt(0);
        //deactivatedTiles.RemoveAt(0);
    }

    private void SpawnTile(int prefabIndex = -1)
    {
        GameObject go;
        if (prefabIndex == -1)
        {
            go = Instantiate(tilePrefabs[RandomPrefabIndex()]) as GameObject;
        }
        else
        {
            go = Instantiate(tilePrefabs[prefabIndex]) as GameObject;
        }

        go.transform.SetParent(transform);
        go.transform.position = Vector3.forward * spawnZ;
        spawnZ += tileLength;
        activeTiles.Add(go);
        //go.SetActive(false);

        //if (deactivatedTiles != null)
        //{
        //    Debug.Log("Has a Tile");
        //    deactivatedTiles[0].SetActive(true);
        //}

        //Debug.Log(deactivatedTiles);
    }

A help would be greatly appreciated.


Solution

  • Instead of deactivating and then re-activating your tiles, you could just move them from the back to the front when needed, like this:

    |---|---|---|---|
    |---|---|---|---|
    
            |
            V
    
        |---|---|---|---|
        |---|---|---|---|
    

    (The first picture is the old state, and the second one is the state after). Instead of

    if (playerTransform.position.z - safeZone > (spawnZ - amtOfTilesOnScreen * tileLength)) {
        SpawnTile();
        DeleteTile();
    }
    

    Do something like

    if (playerTransform.position.z - safeZone > (spawnZ - amtOfTilesOnScreen * tileLength)) {
        if (activeTiles.Count() < (NumberOfTilesThatFitOnScreen + 1)) {
            var spawnedTile = SpawnTileAtFront();
    
            activeTiles.Add(spawnedTile);
        } else {
            var movedTile = activeTiles[0];
            MoveTileToFront(movedTile);
    
            //Puts the moved tile at the end of the array, so the next tile that will be moved is always the one in back
            activeTiles.RemoveAt(0);
            activeTiles.Add(movedTile);
        }
    }
    

    and then implement these two methods like so:

    private void MoveTileToFront(GameObject tile)
    {
        tile.transform.position = Vector3.forward * spawnZ;
        spawnZ += tileLength;
    }
    
    private GameObject SpawnTileAtFront(int prefabIndex = -1)
    {
        GameObject go;
        if (prefabIndex == -1)
        {
            go = Instantiate(tilePrefabs[RandomPrefabIndex()]) as GameObject;
        }
        else
        {
            go = Instantiate(tilePrefabs[prefabIndex]) as GameObject;
        }
    
        go.transform.SetParent(transform);
        MoveTileToFront(go);
        return go;
    }
    

    Set NumberOfTilesThatFitOnScreen to the number of tiles that completely fill the screen.

    Now your game should keep spawning new tiles until there is enough so that if you alter the last or first tile, it won't show on the screen. Then, once this amount is reached, the game should take the last tile (which isn't on screen) and move it to the front (which also shouldn't be on the screen). Then you're character will encounter this tile again, and another off-screen tile will be moved to the front, and so on. Ideally, it would look like the character is on an infinite path