我已经设置了一个似乎可以工作的3D细胞自动机脚本。但我看不到任何典型的CA模式,比如滑翔机或闪光灯等。
我的猜测是,这与我检查邻居的顺序有关。或者我是如何设置基本网格的。
这是Unity的一个动画短片。
这是网格设置部分:
private void CreateGrid(int y)
{
GameObject CellObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
CellObject.transform.localScale = cubeScale;
int i = 0;
for (int z = 0; z < GridWidth; z++)
{
for (int x = 0; x < GridHeight; x++)
{
CellGrid[i] = Instantiate(CellObject, new Vector3(x, y, z), transform.rotation) as GameObject;
CellGrid[i].GetComponent<MeshRenderer>().material = WhiteMat;
i++;
}
}
}
这是生命的游戏部分:
private void GameOfLife()
{
for (int i=0; i < CellGrid.Length; i++)
{
int count = 0;
var CellMat = CellGrid[i].GetComponent<Renderer>().sharedMaterial;
//8 Neighbour Names : NeighNW, NeighN, NeighNE, NeighW, NeighE, NeighSW, NeighS, NeighSE,
//CHECK 1 of 8 NeighSW
if ((i-(GridWidth +1) >= 0 )&& i- (GridWidth + 1) <= CellGrid.Length)
{
var NeighSW = CellGrid[i- (GridWidth + 1)];
var NeighSWmat = NeighSW.GetComponent<Renderer>().sharedMaterial;
if (NeighSWmat != null)
{
if (NeighSWmat != WhiteMat)
{
count++;
//Debug.Log("Black Material found, SW of cell"+ i);
}
else if (NeighSWmat == WhiteMat)
{
//Debug.Log("White Cell SW of " + i);
}
else if (NeighSWmat == TetrinoMat1)
{
count++;
}
}
else
{
Debug.Log("Material Error with Cell no." + i);
}
}
else
{
//Debug.Log("no NeighSW cell " + i);
} //End of NeighSW Check
//CHECK 2 of 8 NeighS
if ((i - (GridWidth) >= 0) && i - (GridWidth) <= CellGrid.Length)
{
var NeighS = CellGrid[i - (GridWidth)];
var NeighSmat = NeighS.GetComponent<Renderer>().sharedMaterial;
if (NeighSmat != null)
{
if (NeighSmat != WhiteMat)
{
count++;
//Debug.Log("Black Material found, S of cell"+ i);
}
else if (NeighSmat == WhiteMat)
{
//Debug.Log("White Cell S of " + i);
}
else if (NeighSmat == TetrinoMat1)
{
count++;
}
}
else
{
Debug.Log("Material Error with Cell no." + i);
}
}
else
{
//Debug.Log("no NeighS cell " + i);
} //End of NeighS Check
//CHECK 3 of 8 NeighSE
if ((i - (GridWidth - 1) >= 0) && i - (GridWidth - 1) <= CellGrid.Length)
{
var NeighSE = CellGrid[i - (GridWidth - 1)];
var NeighSEmat = NeighSE.GetComponent<Renderer>().sharedMaterial;
if (NeighSEmat != null)
{
if (NeighSEmat != WhiteMat)
{
count++;
//Debug.Log("Black Material found, SE of cell"+ i);
}
else if (NeighSEmat == WhiteMat)
{
//Debug.Log("White Cell SE of " + i);
}
else if (NeighSEmat == TetrinoMat1)
{
count++;
}
}
else
{
Debug.Log("Material Error with Cell no." + i);
}
}
else
{
//Debug.Log("no NeighSE cell " + i);
} //End of NeighSE Check
//CHECK 4 of 8 NeighE
if ((i - (GridWidth - 1) >= 0) && i - (GridWidth - 1) <= CellGrid.Length)
{
var NeighE = CellGrid[i - (+ 1)];
var NeighEmat = NeighE.GetComponent<Renderer>().sharedMaterial;
if (NeighEmat != null)
{
if (NeighEmat != WhiteMat)
{
count++;
//Debug.Log("Black Material found, E of cell"+ i);
}
else if (NeighEmat == WhiteMat)
{
//Debug.Log("White Cell E of " + i);
}
else if (NeighEmat == TetrinoMat1)
{
count++;
}
}
else
{
Debug.Log("Material Error with Cell no." + i);
}
}
else
{
//Debug.Log("no NeighE cell " + i);
} //End of NeighE Check
//CHECK 5 of 8 NeighW
if ((i - (1) >= 0) && i - (GridWidth - 1) <= CellGrid.Length)
{
var NeighW = CellGrid[i - 1];
var NeighWmat = NeighW.GetComponent<Renderer>().sharedMaterial;
if (NeighWmat != null)
{
if (NeighWmat != WhiteMat)
{
count++;
//Debug.Log("Black Material found, W of cell"+ i);
}
else if (NeighWmat == WhiteMat)
{
//Debug.Log("White Cell W of " + i);
}
else if (NeighWmat == TetrinoMat1)
{
count++;
}
}
else
{
Debug.Log("Material Error with Cell no." + i);
}
}
else
{
//Debug.Log("no NeighE cell " + i);
} //End of NeighW Check
//CHECK 6 of 8 NeighNW
if ((i + (GridWidth - 1) >= 0) && i + (GridWidth - 1) < CellGrid.Length)
{
var NeighNW = CellGrid[i + (GridWidth - 1)];
var NeighNWmat = NeighNW.GetComponent<Renderer>().sharedMaterial;
if (NeighNWmat != null)
{
if (NeighNWmat != WhiteMat)
{
count++;
//Debug.Log("Black Material found, NW of cell"+ i);
}
else if (NeighNWmat == WhiteMat)
{
//Debug.Log("White Cell NW of " + i);
}
else if (NeighNWmat == TetrinoMat1)
{
count++;
}
}
else
{
Debug.Log("Material Error with Cell no." + i);
}
}
else
{
//Debug.Log("no NeighNW cell " + i);
} //End of NeighNW Check
//CHECK 7 of 8 NeighN
if ((i + (GridWidth) >= 0) && i + (GridWidth) < CellGrid.Length)
{
var NeighN = CellGrid[i + (GridWidth)];
var NeighNmat = NeighN.GetComponent<Renderer>().sharedMaterial;
if (NeighNmat != null)
{
if (NeighNmat != WhiteMat)
{
count++;
//Debug.Log("Black Material found, S of cell"+ i);
}
else if (NeighNmat == WhiteMat)
{
//Debug.Log("White Cell S of " + i);
}
else if (NeighNmat == TetrinoMat1)
{
count++;
}
}
else
{
Debug.Log("Material Error with Cell no." + i);
}
}
else
{
//Debug.Log("no NeighN cell " + i);
} //End of NeighN Check
//CHECK 8 of 8 NeighNE
if ((i + (GridWidth + 1) >= 0) && i + (GridWidth + 1) < CellGrid.Length)
{
var NeighNE = CellGrid[i + (GridWidth + 1)];
var NeighNEmat = NeighNE.GetComponent<Renderer>().sharedMaterial;
if (NeighNEmat != null)
{
if (NeighNEmat != WhiteMat)
{
count++;
//Debug.Log("Black Material found, SE of cell"+ i);
}
else if (NeighNEmat == WhiteMat)
{
//Debug.Log("White Cell SE of " + i);
}
else if (NeighNEmat == TetrinoMat1)
{
count++;
}
}
else
{
Debug.Log("Material Error with Cell no." + i);
}
}
else
{
//Debug.Log("no NeighNE cell " + i);
} //End of NeighNE Check
//COUNT TALLY
//Debug.Log("Cell no." + i + " Neighbour count " + count) ;
//RULE 1 - Any live cell with fewer than two live neighbors dies, as if caused by under-population.
if ((CellMat != WhiteMat) && (count < 2))
{
killCell(i);
}
//RULE 2 - Any live cell with two or three live neighbors lives on to the next generation.
if((CellMat != WhiteMat) && (count >= 2) && (count <=3))
{
DoNothing(i);
}
//RULE 3 - Any live cell with more than three live neighbors dies, as if by overcrowding.
if ((CellMat != WhiteMat) && (count > 3))
{
killCell(i);
}
//RULE 4 - Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
if ((CellMat == WhiteMat) && (count == 3))
{
BirthCell(i);
}
}
}
您的代码有三个缺陷。首先,NeighE
和neighW
的第一个if
子句不正确。此外,NeighE
实际上正在使用西邻居;将CCD_ 5改变为CCD_。
最后,根据您显示的动画的行为,您实现的转换本身是错误的。在元胞自动机中,所有细胞都同时改变状态,因此,如果将一个细胞设置为不同的状态,那么在处理完所有细胞之后,它的邻居才会看到变化。
最简单的方法是双重缓冲:从源缓冲区读取并写入目标缓冲区,然后在完成所有操作后交换它们。避免使用两个缓冲区的另一种可能性是在单个缓冲区中有一个不可见的额外行,从它所在的末尾开始传递,并将每个单元格写入前一行中的单元格,然后移动视图,使最后一行现在是不可见的行,并在下一步中反转方向。