public List <SpawnGroup> GenerateMaze()
    {
        createLogicalMaze();
        GameObject mazeGO = (GameObject)GameObject.Instantiate(_data.mazePrefab, Vector3.zero, Quaternion.identity);

        Dictionary <int, List <Transform> > cellByWalls = new Dictionary <int, List <Transform> >();

        for (int i = 1; i < 6; ++i)
        {
            cellByWalls.Add(i, (new List <Transform>()));
        }

        //This uses Find heavily, so as a result it only makes sense to generate
        //the maze when loading.  It might not even make sense to do it this way
        //regardless
        for (int l = 0; l < LAYS; ++l)
        {
            for (int r = 0; r < ROWS; ++r)
            {
                for (int c = 0; c < COLS; ++c)
                {
                    MazeCell   cell         = _maze.CellAt(r, c, l);
                    GameObject cellGO       = mazeGO.transform.FindChild(string.Format(FIND_CELL_STR, l, r, c)).gameObject;
                    int        n            = 0;
                    bool       needElevator = false;
                    bool       useScoreMat  = false;

                    GameObject tmpGO = cellGO.transform.FindChild("Back").gameObject;
                    tmpGO.SetActive(cell.IsWallEnabled(MazeCell.WallSides.Back));
                    if (tmpGO.activeSelf)
                    {
                        ++n;
                        tmpGO.GetComponent <MeshRenderer>().material = _mcData.defaultMaterial;
                    }

                    tmpGO = cellGO.transform.FindChild("Front").gameObject;
                    tmpGO.SetActive(cell.IsWallEnabled(MazeCell.WallSides.Front));
                    if (tmpGO.activeSelf)
                    {
                        ++n;
                        tmpGO.GetComponent <MeshRenderer>().material = _mcData.defaultMaterial;
                    }

                    tmpGO = cellGO.transform.FindChild("Right").gameObject;
                    tmpGO.SetActive(cell.IsWallEnabled(MazeCell.WallSides.Right));
                    if (tmpGO.activeSelf)
                    {
                        ++n;
                        tmpGO.GetComponent <MeshRenderer>().material = _mcData.defaultMaterial;

                        useScoreMat = (Random.Range(0, 100) > 89);
                        if (useScoreMat)
                        {
                            GameObject scoreGO = GameObject.CreatePrimitive(PrimitiveType.Quad);
                            scoreGO.GetComponent <Collider>().enabled = false;
                            scoreGO.transform.parent        = tmpGO.transform;
                            scoreGO.transform.localRotation = Quaternion.Euler(90 * Vector3.up);
                            scoreGO.transform.localScale    = Vector3.one;
                            scoreGO.transform.localPosition = -0.71f * Vector3.right;
                            scoreGO.GetComponent <MeshRenderer>().material       = _mcData.scoreMaterial;
                            scoreGO.GetComponent <MeshRenderer>().receiveShadows = false;
                        }
                    }

                    tmpGO = cellGO.transform.FindChild("Left").gameObject;
                    tmpGO.SetActive(cell.IsWallEnabled(MazeCell.WallSides.Left));
                    if (tmpGO.activeSelf)
                    {
                        ++n;
                        tmpGO.GetComponent <MeshRenderer>().material = _mcData.defaultMaterial;
                        if (useScoreMat)
                        {
                            GameObject scoreGO = GameObject.CreatePrimitive(PrimitiveType.Quad);
                            scoreGO.GetComponent <Collider>().enabled = false;
                            scoreGO.transform.parent        = tmpGO.transform;
                            scoreGO.transform.localRotation = Quaternion.Euler(270 * Vector3.up);
                            scoreGO.transform.localScale    = Vector3.one;
                            scoreGO.transform.localPosition = 0.71f * Vector3.right;
                            scoreGO.GetComponent <MeshRenderer>().material       = _mcData.scoreMaterial;
                            scoreGO.GetComponent <MeshRenderer>().receiveShadows = false;
                        }
                    }

                    tmpGO = cellGO.transform.FindChild("Top").gameObject;
                    tmpGO.SetActive(cell.IsWallEnabled(MazeCell.WallSides.Top));
                    if (tmpGO.activeSelf)
                    {
                        ++n;
                        tmpGO.GetComponent <MeshRenderer>().material = _mcData.defaultMaterial;
                    }
                    else
                    {
                        needElevator = true;
                    }

                    tmpGO = cellGO.transform.FindChild("Bottom").gameObject;
                    tmpGO.SetActive(cell.IsWallEnabled(MazeCell.WallSides.Bottom));
                    if (tmpGO.activeSelf)
                    {
                        ++n;
                        tmpGO.GetComponent <MeshRenderer>().material = _mcData.defaultMaterial;
                        if (needElevator)
                        {
                            Transform  btm   = tmpGO.transform;
                            GameObject eleGO = (GameObject)GameObject.Instantiate(_data.elevatorTriggerPrefab, btm.position, Quaternion.identity);
                            eleGO.name = "Elevator" + btm.position.ToString();
                        }
                    }

                    if (cell == _endCell)
                    {
                        AudioSource src = cellGO.AddComponent <AudioSource>();
                        src.clip        = _data.endCellSound;
                        src.spread      = 0.0f;
                        src.rolloffMode = AudioRolloffMode.Linear;
                        src.maxDistance = 32.0f;
                        src.loop        = true;
                        src.volume      = 0.4f;
                        src.Play();
                    }
                    cellByWalls[n].Add(cellGO.transform);
                }
            }
        }

        disableDuplicateWalls(mazeGO);

        return(createSpawnGroups(cellByWalls));
    }