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:
- A live cell with one or zero neighbours dies due to underpopulation.
- A live cell with two or three neighbours lives.
- A live cell with more than three neighbours dies due to overpopulation.
- 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.
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.
https://waterfallmagazine.com
Hi, this weekend is nice designed for me, because this time
i am reading this enormous informative paragraph here at my house.