Skip to content

Conway’s Game Of Life in 3D

Evolution!

We are now adding code to repeatedly invoke a specific method called nextGeneration:

    void Start () 
    {
        initialSetup();

        InvokeRepeating("nextGeneration", 1.0f, 1.0f);
    }

    private void nextGeneration()
    {
        for (int i = 0; i < matrix.GetLength(0); i++)
        {
            for (int j = 0; j < matrix.GetLength(1); j++)
            {
                for (int k = 0; k < matrix.GetLength(2); k++)
                {
                    // TODO: figure out if the current cube survives based on its neighbours
                }
            }
        }
    }
}

Now, again the above code doesn't do much other than waste resources. In order to verify and confirm that the nextGeneration method is actually repeatedly called, let's add some code to simply toggle the visibility of all GameObjects. The expectation then is that the entire grid will toggle between being visible and invisible:

    void Start () 
    {
        initialSetup();

        InvokeRepeating("nextGeneration", 1.0f, 1.0f);
    }

    private void nextGeneration()
    {
        for (int i = 0; i < matrix.GetLength(0); i++)
        {
            for (int j = 0; j < matrix.GetLength(1); j++)
            {
                for (int k = 0; k < matrix.GetLength(2); k++)
                {
                    // TODO: figure out if the current cube survives based on its neighbours
                    matrix[i, j, k].SetActive(!matrix[i, j, k].activeSelf);
                }
            }
        }
    }
}

The result is as we expected:

Let's implement Conway's rules that will determine, which Cubes to enable or disable in any given generation. As a reminder, the rules are:


  1. A live cell with one or zero neighbours dies due to underpopulation.
  2. A live cell with two or three neighbours lives.
  3. A live cell with more than three neighbours dies due to overpopulation.
  4. A dead cell with exactly three live neighbours comes to live due to reproduction.

First, let's figure out how many neighbours each cube location currently has:

    private int currentNeighbours(int x, int y, int z)
    {
        int neighbours = 0;
        for (int i = -1; i <= 1; i++)
        {
            for (int j = -1; j <= 1; j++)
            {
                for (int k = -1; k <= 1; k++) 
                { 
                    int curX = x+i;
                    int curY = y+j;
                    int curZ = z+k;

                    if (x == curX && y == curY && z == curZ)
                    { 
                        // this is the cube under test and since the
                        // current state of the cube is ignored, we
                        // continue at this point continue;
                    } 

                    if (curX >= 0 && curX < xCubes 
                        && curY >= 0 && curY < yCubes
                        && curZ >= 0 && curZ < zCubes)
                    {
                        if (matrix[curX, curY, curZ].GetComponent().enabled)
                        {
                            neighbours++;
                        }
                    }
                }
            }
        }

        return neighbours;
    }

Now for the most exciting part, we make use of the currentNeighbours method as part of the nextGeneration method:

    private void nextGeneration()
    {
        bool[,,] newArr = new bool[xCubes, yCubes, zCubes];

        // calculate the next generation
        for (int i = 0; i < matrix.GetLength(0); i++)
        {
            for (int j = 0; j < matrix.GetLength(1); j++)
            {
                for (int k = 0; k < matrix.GetLength(2); k++)
                {
                    int neighbours = currentNeighbours(i, j, k);

                    GameObject curCube = matrix[i, j, k];
                    Renderer renderer = curCube.GetComponent();

                    if (renderer.enabled)
                    {
                        // rule 1 - underpopulation, you die
                        if (neighbours <= 1) 
                        { 
                            newArr[i, j, k] = false; 
                            continue; 
                        }
 
                        // rule 2 - you survive
                        if (neighbours == 2 || neighbours == 3) 
                        { 
                            newArr[i, j, k] = true; 
                            continue; 
                        }
 
                        // rule 3 - overpopulation, you die
                        if (neighbours > 3)
                        {
                            newArr[i, j, k] = false;
                            continue;
                        }
                    }
                    else
                    {
                        // rule 4 - you are born
                        if (neighbours == 3)
                        {
                            newArr[i, j, k] = true;
                        }
                    }
                }
            }
        }

        // update the visibility of all cubes
        for (int i = 0; i < newArr.GetLength(0); i++)
        {
            for (int j = 0; j < newArr.GetLength(1); j++)
            {
                for (int k = 0; k < newArr.GetLength(2); k++)
                {
                    GameObject curCube = matrix[i, j, k];
                    Renderer renderer = curCube.GetComponent();

                    renderer.enabled = newArr[i, j, k];
                }
            }
        }
    }

The nextGeneration method requires a bit of explanation:

The loop between lines 6 - 50 determines the state of the next generation for each and every cube. The second loop between lines 53 and 65 then updates each cube, essentially moving forward one generation. The reason this logic is split into two different for loops is to ensure that the first for loop doesn't modify the states of any cubes before the remaining cubes had a chance to figure out if they will survive or die in the next generation.

The result is very promising but obviously has a very short lifetime, mostly because of tremendous overpopulation:

Alright, now that we have a 2D implementation working, the next chapter will modify the code to work with 3D.

2 thoughts on “Conway’s Game Of Life in 3D

  1. telepathy

    Heya i'm foг the first time here. I found this board and Ӏ find It reallү useful & it heⅼped me out muсh.
    I hope to givе something back and aid others like you aided me.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *