Object Pooling

Hi there! I am really quite stuck on how to properly do object pooling for my 3D endless runner game. I have this TileManager script that works perfectly but it causes lag on mobile devices because it has to constantly instantiate and destroy objects. I am just getting really confused on how to change the script to use object pooling.

I understand I need to instantiate the objects right off the start then store them in a pool. Then from that pool, I would need to move the objects position. I do not know how to go about all of this. If anyone could help by showing me what I need to do to the script that would be greatly appreciated! Thank you!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TileManager : MonoBehaviour {

    //Tile Variables
    public GameObject[] tilePrefabs;

    public static Transform playerTransform;
    private float spawnZ = -13.0f;
    private float tileLength = 13.0f;
    private float safeZone = 12.0f;
    private int amnTilesOnScreen = 4;
    private int lastPrefabIndex = 0;

    public List<GameObject> activeTiles;

    // Use this for initialization
    private void Start () {
        activeTiles = new List<GameObject>();
        playerTransform = GameObject.FindGameObjectWithTag("Player").transform;


        for (int i = 0; i < amnTilesOnScreen; i++)
        {
            if (i < 2)
                SpawnTile(0);
            else
                SpawnTile();
        }
    }
   
    // Update is called once per frame
    private void Update () {
        if (playerTransform.position.z - safeZone > (spawnZ - amnTilesOnScreen * tileLength))
        {
            SpawnTile();
            DeleteTile();
        }
    }

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

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

    private void DeleteTile()
    {
        Destroy(activeTiles[0]);
        activeTiles.RemoveAt(0);
    }

    private int RandomTilePrefabIndex()
    {
        if (tilePrefabs.Length <= 1)
            return 0;

        int randomIndex = lastPrefabIndex;
        while (randomIndex == lastPrefabIndex)
        {
            randomIndex = Random.Range(0, tilePrefabs.Length);
        }

        lastPrefabIndex = randomIndex;
        return randomIndex;
    }

   
}

The point of object pooling is basically to never need to use instantiate ( after start of game or level ) or destroy.
How many tiles are maximum seen on the screen ever? Make activeTiles an array of that size ( arrays are slightly faster than Lists due to fixed data size ) Spawn your tiles at start and fill the activeTiles with those. Then just set activeTiles[youChoose].transform.position and activeTiles[youChoose].setActive() etc.

If you want faster loading times it might be helpful to have all those tile GameObjects in your first scene already linked to activeTiles in the editor then move them with the pooling scripts through all the scenes in a singleton.

EDIT:
You’ll need an activeTiles for every different prefab you got after reading you’re doing an endless runner with probably lots of different tilePrefabs?

I will do some trial and error and see if I can get this to work. Thank you for guiding me in the right direction!