Replace random a prefab in a Grid with a random prefab from resources

I create a grid with neutral boxes with:

public class GridManager : MonoBehaviour
{
    public float x_Start, y_Start;
    public int columnLength, rowLength;
    public float x_Space, ySpace;
    public GameObject neutralBoxGrid;

    //Create a Grid with the neutral Box
    void Start()
    {
        if (neutralBoxGrid == null)
            neutralBoxGrid = GameObject.FindGameObjectWithTag("neutral");


        for (int i = 0; i < columnLength * rowLength; i++)
        {
           Instantiate(neutralBoxGrid, new Vector3(x_Start + (x_Space * (i % columnLength)), y_Start + (-ySpace * (i / columnLength))), Quaternion.identity);

        }
       
    }

That gives me for example a grid 2x2 with 4 cloned neutralBoxes

I like to replace randomly every x seconds 1 of the cloned boxes with a prefab of the resources folder
In my GameLogicScript i get the boxes with:

//Make sure the boxes are in

        blackBox = Resources.Load("BoxBlack") as GameObject;
        blueBox = Resources.Load("BoxBlue") as GameObject;
        greenBox = Resources.Load("BoxGreen") as GameObject;

How can i choose a random cloned object, and how do i replace it with 1 prefab of the resource folder every x seconds?
For a start i created a tagsArray with my boxesPrefabs of the resource folder:

int  randomIndex = Random.Range(0, 7);
       string randomTag = tagsArray[randomIndex];
       pointObject = GameObject.FindWithTag(randomTag);
        Debug.Log("I found" + pointObject);
        pointObject = pointObjectCount;

There are a bunch of things you should change.
the method GameObject.FindGameObjectWithTag is extremly slow - at this point, it may be ok, because you only check it once your script starts (if it is active by default, this will also be when the game starts) and only if the value is NULL - but the NULL-Check is the next one xD
Unity does something special when destroying an UnityEngine.Object, thats why you should always use the bool operator overload for any NULL-Check like so: if (!neutralBoxGrid) without the == null
Because when you destroy the object in the same frame, == null will return false, even when the object is theoretically null.

Resources.Load whatever object you have in your ressources, will be loaded when the game starts. So if you have many objects in your ressources, the game will take ages to load even when just starting the main menu.
If you assign those objects in the inspector, it will only be loaded when it is needed - so it won’t load them in the main menu for example, but when you start your game scene. (also you can rename them without losing the references to them in your scripts / in the inspector)

You could use a coroutine or InvokeRepeating to execute something every X seconds.

To identify your objects, there are a lot of ways to do this …
For all the solutions that come to my mind right now, you should keep track of your instances. Instantiate() returns a GameObject, the instance you just created.
Store this instance in any collection … it could be a list, or as you said this is a grid with a fixed size - store it in a two dimensional Array GameObject[,] instanceGridArray; .

Option Nr1: Create a new script (MonoBehaviour) and attach it to your cubes. Add a string, enum or int as identifier and store the script instead of the GameObject in your Array CubeIdentifier[,] instanceGridArray; , instanceGridArray[x,y] = Instantiate([...]).GetComponent<CubeIdentifier>();.
To check if a cube is of a specific type, just call instanceGridArray[x,y].myIdentityValue; “myIdentityValue” is of course a field inside the “CubeIdentifier” script which is a “string, enum or int” as mentioned earlier.
Then you can replace them and update the grid the same way you did, when instantiating the neutral cubes.

Option Nr2: Basically the same as above but using names for the identity

Option Nr3: Basically the same as above but you store a custom c# class which is not a monobehaviour in your array and the custom class can hold any information like the identity value - and you don’t have to add this information to your instances.

So you should create a proper data layout for your grid and everything else will be quite simple then.

Also you should avoid using tags, you only have one tag per object and if two different systems use them, one object cannot be used by both systems …

1 Like

Ty,
i have started so:

public float changeBoxesEachXSeconds = 0;
        GameObject[] BoxAvatars;

        [System.Serializable]
        public class BoxType
        {
            public string name;
            public BoxTypology typology;
            public int odds;
            public GameObject Avatar;
             public AudioClip pickAudioFx;

        }
        public BoxType[] boxes;

        public enum BoxTypology
        {

I have it running that 1 box change ever x Seconds with invoke method.
And i created for it an own script
I think i can go further now :slight_smile:

1 Like