optimizing for loops

(preface: sorry for the rapidfire questions i posted like 3 this day but im really struggling with this algorithm)

im semi-ok at coding but not very good at optimizing. and im attempting to make Conway’s game of life which at larger scales can be resource intensive (in my case cause ima noob). this is the only script i have in my scene rn

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

public class TileManager : MonoBehaviour
{
    public Tilemap TM;
    private Vector3Int Pos;
    private int TotalBorder;
    public TileBase Alive;

    public void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {

            Sequence();
        }
    }
//runs through every tile in a tile map after compressing bounds (expanded to account for growth
    public void Sequence()
    {
        TM.CompressBounds();

        for (int n = TM.cellBounds.xMin - 2; n < TM.cellBounds.xMax + 2; n++)
        {
            for (int p = TM.cellBounds.yMin - 2; p < TM.cellBounds.yMax + 2; p++)
            {
//gets the local vectorint

                Vector3Int localPlace = (new Vector3Int(n, p, (int)TM.transform.position.y));
//checks if the target tile is active
                if (TM.HasTile(localPlace))
                {
                    Check(n, p, true);
                }
                else
                {

                    Check(n, p, false);
                }
            }
        }

    }
//checks the state of the tiles around the target tile
    public void Check(int n, int p, bool state)
    {

        if (state == true)
        {
            Pos = new Vector3Int(n, p, (int)TM.transform.position.y);
            for (int i = -1; i <= 1; i++)
            {
                for (int j = -1; j <= 1; j++)
                {
                    Vector3Int pos = new Vector3Int(n + i, p + j, (int)TM.transform.position.y);
//checks if the tile they are trying to check has an offset of (0, 0) aka the target tile
                    if (pos != Pos)
                    {
           
                
                        if (TM.GetTile(new Vector3Int(n + i, p + j, (int)TM.transform.position.y)))
                        {
                            TotalBorder++;
                        }




                    }

                }

            }
            if(TotalBorder == 0)
            {
                StartCoroutine(ChangeTile(Pos, false));

            }
            else if (TotalBorder == 1)
            {
                StartCoroutine(ChangeTile(Pos, false));

            }
            else if (TotalBorder == 2)
            {
                StartCoroutine(ChangeTile(Pos, false));

            }
            else if (TotalBorder == 5 || TotalBorder > 5)
            {
                StartCoroutine(ChangeTile(Pos, false));
            }

            TotalBorder = 0;
        }
        else
        {

  
                Pos = new Vector3Int(n, p, (int)TM.transform.position.y);
                for (int i = -1; i <= 1; i++)
                {
                    for (int j = -1; j <= 1; j++)
                    {
                        Vector3Int pos = new Vector3Int(n + i, p + j, (int)TM.transform.position.y);
//checks if the tile they are trying to check has an offset of (0, 0) aka the target tile
                        if (pos != Pos)
                        {
                  

                            if (TM.GetTile(new Vector3Int(n + i, p + j, (int)TM.transform.position.y)))
                            {
                                TotalBorder++;
                            }




                        }

                    }

                }

                if(TotalBorder == 2)
                {
                StartCoroutine(ChangeTile(Pos, true));

                }
          
                else  if (TotalBorder == 3)
                {
                    StartCoroutine(ChangeTile(Pos, true));

                }
      
      
                TotalBorder = 0;
    
        }
    }
//changed the tile from alive to dead. wait till end of frame to keep changes from effecting eachother inbetween generations.
    public IEnumerator ChangeTile(Vector3Int Pos, bool changetype)
    {
        yield return new WaitForEndOfFrame();
        if (changetype == false)
        {
            TM.SetTile(Pos, null);

        }
        else
        {
            TM.SetTile(Pos, Alive);
        }


    }

}

what i want to know if there’s any more efficient way to do this (after a couple generations it gets really laggy for obvious reasons)
ive done some research and found algorithms for pathfinding but i dont know if that will for what i need.

Hi,

I guess you should try to figure out what in the loops are taking the resources, and concentrate on optimizing those parts of the code. Perhaps all tiles doesn’t have to be looped over every time the spacebar is pressed? Do the TM.CompressBounds(); has to run every single frame? And maybe its better to build a todo-list of Tiles to change, and execute all of them in one single loop at the end of the frame, instead of starting loads of Couroutines for each Tile?

Using coroutines is definitely inappropriate here.

The brute force reference way to implement Conway’s GOL is to have two 2-dimensional arrays, one for each generation, and simply switch between them each generation.

Array A contains the starting generation.

“Do the work” to fill Array B with the second generation

Display Array B in whatever fashion you like

Switch A and B and repeat.

If you want it REALLY fast, consider using DOTS .

1 Like

Conways GOL is one of those great “can I still do this whole programming thing?” questions to ask yourself.

I try to implement such things at least once a year… keeps you honest about your capabilities.

Here’s one I ripped out in the past 23 minutes after I posted the above:

Note the conspicuous lack of coroutines. :slight_smile:

Seems to work… let me know if you spot any bugs. Always love to hear about my mistakes, as that’s the only way one improves oneself.

ok ill try to do this. to be honesty i had no idea what a dimensional array, i see you have a maximum canvas size for the game. is there a way to make it scale with the game so its infinite?

i will look into making a list of all tiles that need to be changed and changing them all at the end of the frame i think that one will cause the most lag reduction