Game of life also known as Conway's game of life is a model that simulates the creation, existence, and destruction of life. This model is based on the fact that life cannot exist when there is an under or overpopulation and under the right conditions there is a chance of reproducing real life.

This model consists of cells arranged in a grid. Each cell can be in two-state i.e dead and alive. The state of the cell is determined by the state of its neighbours. State of eight neighbours (top, bottom, left, right, and four diagonal cells) are used to set the state of a cell. It consists of four rules that will decide the state of a cell in the next step.

Rule 1: Cell with less than 2 alive neighbours dies

This rule is showing the effect of underpopulation on a cell. A cell with few neighbours cannot get enough help from its neighbour causing it to die.

Middle cell dying
Rule 2: Cell with 2 or 3 alive neighbours will continue to live

This simulates the ideal condition for the cell to live where there is a right number of neighbours.

Middle cell surviving
Rule 3: Cell with more than 3 alive neighbours dies

This is simulating a case where a creature dies due to overpopulation.

Middle cell dying
Rule 4: A dead cell with 3 neighbours will get life

This simulates an ideal condition for reproduction hence creating new cells.

Middle cell getting reproduced

Using these 4 rules we can build this model. These rules can be simplified to the following 3 steps:

  1. A live cell with 2 or 3 alive neighbouring cells survives
  2. A dead cell with 3 neighbouring cells will get alive
  3. All other cells die

Building Game of Life in unity

First, we will need a Cell the class that will store a cell's state and will help in making cells dead or alive. We can simply store the status of a cell in bool, making it alive or dead. To represent the state of a cell, we will create a UI image and set its colour.

public Image image; //an image for showing state of cell
public bool isCellAlive; //store status of cell
private bool markedAlive, markedDead; //we will update status of cell in two steps.
//first mark all cells dead or alive acording to it's neighbours
//then update state of cells after all cells are marked
public Color aliveColor, deadColor; //colours we set from editor to indicate dead and alive cell

//set colour of cell at the start according to starting state
private void Awake() {
  image.color = isCellAlive ? aliveColor : deadColor;
}

//mark a cell as dead or alive. This will not change the state, just mark for later
public void MarkDead() {
  markedDead = true;
}

public void MarkAlive() {
  markedAlive = true;
}

//update the state of cell. The cell will be dead or alive if it was marked previously
public void UpdateCell() {
  if (markedAlive) {
    ActivateCell();
  }
  if (markedDead) {
    DeactivateCell();
  }
}

//theese methods will kill and revive cells
public void ActivateCell() {
  markedAlive = false;
  markedDead = false;
  isCellAlive = true;

  image.color = aliveColor; //update graphics
}

public void DeactivateCell() {
  markedAlive = false;
  markedDead = false;
  isCellAlive = false;

  image.color = deadColor; //update graphics
}

//mouse pointers input handlere. cell will switch state if clicked
public void OnPointerEnter(PointerEventData eventData) {
  if (Input.GetMouseButton(0)) {
    if (isCellAlive) {
      DeactivateCell();
    } else {
      ActivateCell();
    }
  }
}

public void OnPointerDown(PointerEventData eventData) {
  if (isCellAlive) {
    DeactivateCell();
  } else {
    ActivateCell();
  }
}

Now our cell is created, we will create a controller for the game of life. This will be responsible for setting the state of a cell, initializing, or creating a cell. First, create cells according to the given cell count.

public int cellCount_X, cellCount_Y; //number of cells in row and column
public Cell[][] cells; //holder to store cells. we will store them in row and columt
public Cell cellPrefab; //cell prefab that will be initialized
public Transform parent; //parent to hold all cells in game
void CreateCells() {
  cells = new Cell[cellCount_X][];
  for (int i = 0; i < cellCount_X; i++) {
    cells[i] = new Cell[cellCount_Y];
    for (int j = 0; j < cellCount_Y; j++) {
      //instantiate cells and store them
      Cell cell = Instantiate(cellPrefab, new Vector3(i, j), quaternion.identity, parent);
      cells[i][j] = cell;
      cells[i][j].name = $ "cell{i}{j}";
    }
  }
}

Now, update the cells according to the rules

public float updateTime; //call update cells to update cell. We can use coroutines or just create timer system to make repreated calls to it

void UpdateCells() {
  //start checking and marking cells
  for (int i = 0; i < cells.Length; i++) {
    for (int j = 0; j < cells[i].Length; j++) {
      //find numbers of live neighbours. Also don't forget to skip corner and edge cells. they will have fewer number of neighbours.
      int liveNeighbours = 0;

      //check bottom, left
      if (i > 0 && j > 0 && cells[i - 1][j - 1].isCellAlive) {
        liveNeighbours++;
      }

      //check bottom
      if (j > 0 && cells[i][j - 1].isCellAlive) {
        liveNeighbours++;
      }

      //check bottom right
      if (i < cells.Length - 1 & j > 0 && cells[i + 1][j - 1].isCellAlive) {
        liveNeighbours++;
      }

      //check for right
      if (i > 0 && cells[i - 1][j].isCellAlive) {
        liveNeighbours++;
      }

      //check for left
      if (i < cells.Length - 1 && cells[i + 1][j].isCellAlive) {
        liveNeighbours++;
      }

      //check for top left
      if (i > 0 && j < cells[i].Length - 1 && cells[i - 1][j + 1].isCellAlive) {
        liveNeighbours++;
      }

      //check for top
      if (j < cells[i].Length - 1 && cells[i][j + 1].isCellAlive) {
        liveNeighbours++;
      }

      //check for top right
      if (i < cells.Length - 1 && j < cells[i].Length - 1 && cells[i + 1][j + 1].isCellAlive) {
        liveNeighbours++;
      }

      //now after finding the neighbour, we can check rule to mark them dead of alive for next update
      //Rule 1: A live cell with 2 or 3 alive neighbouring cells survives
      if (cells[i][j].isCellAlive && (liveNeighbours == 2 || liveNeighbours == 3)) {
        continue;
      }
      //Rule 2:A dead cell with 3 neighbouring cells will get alive
      if (!cells[i][j].isCellAlive && liveNeighbours == 3) {
        cells[i][j].MarkAlive();
        continue;
      }

      //Rule 3: All other cells dies
      cells[i][j].MarkDead();
    }
  }

  //All cells are marked so update all cells.
  for (int i = 0; i < cells.Length; i++) {
    for (int j = 0; j < cells[i].Length; j++) {
      cells[i][j].UpdateCell();
    }
  }

}

These scripts will create the game of life model. We can make changes to the scripts to implement features such as initializing with a random value, pausing and playing simulation, etc.

Game of life

Final thoughts on Game Of Life

It is a simple model that shows how few simple rules can result in complex behaviours. Even if this model has no real-life application, it gives us an idea of how real-life exists and continues to survive. The chaotic nature of this model is another interesting aspect of it. Even a single minor change results in a very large change. As simple as it looks, people have created many interesting things from it. People have created a simple computer system using this model implementing logic gates from this. Just keep on messing with it and you will find many interesting things to do with it.