포스트

[ Unity ] (solution) 플레이 불가능 맵 발생

분석


특수 블록을 배치하여 게임 진행 시,

일부 셀 값에서 null이 발생, 게임이 진행되지 않는 경우가 발생했다.

이를 확인해본 결과, 아래 그림과 같은 형태로 특수 블록이 배치되었을 때, 빈 셀을 채우지 못해 해당 셀들이 블록이 없어 발생한 것으로 확인됬다.

해결


따라서 이를 해결하기 위해 각 셀 간의 연결 여부를 판단한다.

그리드는 아래와 같은 구조로 각 셀에 여러 데이터들이 저장되어있으며, 주변 셀 정보도 저장되어있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class MatchGrid
{
	List<GridCell> Cells;
}

class GridCell
{
	int Row;
	int Column;
	
	Column<GridCell> GColumn; // List<GridCell> Cells를 Column순 정렬
	Row<GridCell> GRow; // List<GridCell> Cells를 Row순 정렬
	
	int objectID;

	List<GridCell> fillPathToSpawner;
	NeighBors Neighbors;
	bool isAvailable;
}

class Column
{
	List<GridCell> Cells;
	GridCell spawner; // col: 0의 cell
}

class NeighBors
{
	GridCell Main;
	GridCell Left;
	GridCell Right;
	GridCell Top;
	GridCell Bottom; 
	List<GridCell> Cells ;
}

그리고 이를 활용, 해당 셀에서 재귀적으로 탐색하여 루트를 만든다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

public void CreateFillPath(MatchGrid g)
{
    foreach (var c in g.Cells)
    {

        if (!c.spawner)
        {
			// 이동할 수 있는 블록인지 판단
            if (!c.Blocked && !c.IsDisabled && !c.MovementBlocked)
            {
                Stack<GridCell> path = new Stack<GridCell>();
                CreatePathes(map, c.pfCell, c.pfCell, path);
            }
        }

    }
}



public void CreatePathes(Map WorkMap, PFCell A, PFCell current, Stack<GridCell> currentPath)
{
    if (current.mather == null)
    {
        current.mather = current;

        if (current.Neighbors.Top != null)
        {
            finding(WorkMap, A, current.Neighbors.Top.pfCell, currentPath);
        }

        if (current.Neighbors.Left != null)
        {
            finding(WorkMap, A, current.Neighbors.Left.pfCell, currentPath);
        }

        if (current.Neighbors.Right != null)
        {
            finding(WorkMap, A, current.Neighbors.Right.pfCell, currentPath);
        }
    }
}




public void finding(Map WorkMap, PFCell A, PFCell current, Stack<GridCell> currentPath)
{
    if (current.mather == null)
    {
        current.mather = current;

        if (!current.gCell.Blocked && !current.gCell.IsDisabled && !current.gCell.MovementBlocked)
        {
            if (current.gCell.spawner)
            {
                if (A.gCell.fillPathToSpawner != null)
                {
                    if (current.gCell.fillPathToSpawner == null)
                    {
                        A.gCell.fillPathToSpawner = new List<GridCell>();
                        currentPath.Push(current.gCell);

                        foreach (var c in currentPath)
                        {
                            c.pfCell.mather = c.pfCell;
                            A.gCell.fillPathToSpawner.Add(c);
                        }
                        currentPath.Pop();
                    }

                    else
                    {
                        if (currentPath.Count + current.gCell.fillPathToSpawner.Count < A.gCell.fillPathToSpawner.Count)
                        {
                            A.gCell.fillPathToSpawner = new List<GridCell>();
                            currentPath.Push(current.gCell);
                            foreach (var c in currentPath)
                            {
                                c.pfCell.mather = c.pfCell;
                                A.gCell.fillPathToSpawner.Add(c);
                            }
                            currentPath.Pop();
                        }
                    }


                }

                else
                {
                    A.gCell.fillPathToSpawner = new List<GridCell>();
                    currentPath.Push(current.gCell);
                    foreach (var c in currentPath)
                    {
                        c.pfCell.mather = c.pfCell;
                        A.gCell.fillPathToSpawner.Add(c);
                    }

                    currentPath.Pop();
                }


            }

            else
            {
                if (current.gCell.fillPathToSpawner != null)
                {
                    if (current.gCell.fillPathToSpawner[current.gCell.fillPathToSpawner.Count - 1].spawner)
                    {
                        if (A.gCell.fillPathToSpawner != null)
                        {
                            if (currentPath.Count + current.gCell.fillPathToSpawner.Count + 1 < A.gCell.fillPathToSpawner.Count)
                            {
                                A.gCell.fillPathToSpawner = new List<GridCell>();
                                currentPath.Push(current.gCell);

                                foreach (var c in currentPath)
                                {
                                    c.pfCell.mather = c.pfCell;
                                    A.gCell.fillPathToSpawner.Add(c);
                                }

                                foreach (var c in current.gCell.fillPathToSpawner)
                                {
                                    c.pfCell.mather = c.pfCell;
                                    A.gCell.fillPathToSpawner.Add(c);
                                }
                                currentPath.Pop();
                            }
                        }

                        else
                        {

                            A.gCell.fillPathToSpawner = new List<GridCell>();
                            currentPath.Push(current.gCell);

                            foreach (var c in currentPath)
                            {
                                c.pfCell.mather = c.pfCell;
                                A.gCell.fillPathToSpawner.Add(c);
                            }

                            foreach (var c in current.gCell.fillPathToSpawner)
                            {
                                c.pfCell.mather = c.pfCell;
                                A.gCell.fillPathToSpawner.Add(c);
                            }

                            currentPath.Pop();
                        }
                    }
                }

            }
        }
    }
}

그래서 이를 통해 빈 셀이 채워지는데,

이러한 경우, 특수 블록이 스폰 위치와의 루트 생성을 막아 빈 셀을 채울 수 없게 된다.

이러한 경우를 방지하기 위해 fillPathToSpawner가 null인 경우, 이를 플레이할 수 없는 맵이라 판단하고, 이를 플레이하지 않는다.

1
2
3
4
5
if(grid.Cells[i].fillPathToSpawner == null)
{
	return false;
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.