Unity & C#

Grid System (1) - 격자 구조 만들기

coucou3 2020. 5. 10. 19:24
반응형

Grid System

 

Unity에서 Grid System은 퍼즐, 보드 게임에서 많이 사용된다.

가로 길이(width)와 세로 길이(height)가 있는 2차원 좌표계의 게임 보드를 만들어보자.

 

 

 

 

 

1. 개념 구현

Grid class

 

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
public class TestGrid
{
    private int _width;
    private int _height;
    private int _cellSize;
 
    private int[,] _gridArray;
    private TextMesh[,] _textMeshes; 
 
 
    public TestGrid(int width, int height, int cellSize)
    {
        _width = width;
        _height = height;
        _cellSize = cellSize;
 
        _gridArray = new int[width, height];
        _textMeshes = new TextMesh[width, height];
 
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                _gridArray[x, y] = 0;
 
                var position = GetWorldPosition(x, y);
                // 현재 위치의 값을 TextMesh로 나타내준다.
                _textMeshes[x, y] = SUtility.CreateTextToWorld(_gridArray[x, y].ToString(),
                    position + new Vector3(cellSize, cellSize) * 0.5f, 20, Color.white);
                
                // 테두리를 그려준다
                Debug.DrawLine(GetWorldPosition(x, y), GetWorldPosition(x + 1, y), Color.white, 999);
                Debug.DrawLine(GetWorldPosition(x, y), GetWorldPosition(x, y + 1), Color.white, 999);
            }
        }
    }
 
 
    private Vector3 GetWorldPosition(int x, int y)
    {
        return new Vector3(x, y) * _cellSize;
    }
}
 
cs

 

 

간단하게 Grid System을 구현했다.

 

width와 height를 받아 width * height 크기만큼의 int형 2차원 배열을 만들었고,

cellSize의 간격을 지닌 격자를 생성한다.

보기 쉽게 각 셀의 위치에 TextMesh를 지닌 Object를 배치해 현재 좌표의 value를 나타내준다.

 

Debug.DrawLine으로 선도 그렸다

 

 

 

 

User Input과 Interactive하게 동작하도록 추가해보자

클릭시 value += 1을 적용한다.

 

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
public class TestGrid 
{
    ...
    
    // worldPosition을 cellSize로 나누어 grid에서의 위치를 구한다.
    private void GetXY(Vector3 position, out int x, out int y)
    {
        x = Mathf.FloorToInt(position.x / _cellSize);
        y = Mathf.FloorToInt(position.y / _cellSize);
    }
    
    
    public void SetValue(Vector3 position, int value)
    {
        int x, y;
        GetXY(position, out x, out y);
 
        _gridArray[x, y] = value;
        _textMeshes[x, y].text = value.ToString();
    }
 
 
    public int GetValue(Vector3 position)
    {
        int x, y;
        GetXY(position, out x, out y);
 
        return _gridArray[x, y];
    }
}
 
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class GameManager : MonoBehaviour
{
    private TestGrid _grid;
    
    
    void Start()
    {
        _grid = new TestGrid(10105);
    }
 
 
    private void Update()
    {
        if (Input.GetMouseButtonUp(0))
        {
            var worldPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            
            _grid.SetValue(worldPosition, _grid.GetValue(worldPosition) + 1);
        }
    }
}
cs

 

 

 

 

클릭(정확히는 MouseButtonUp)을 했을 때 Input.mousePosition을 기준으로 해당 좌표에 해당하는 값을 1씩 더해준다.

 

 

 

 

 

 

2. GameObject로 GameBoard 구현

 

 

이번에는 실제 게임에 적용할 수 있도록 GameObject로 Grid 형식의 게임판을 만들어보자.

 

먼저 하나의 칸을 나타내는 Tile class를 만든다.

Tile에는 위치를 나타내는 x, y와 값을 나타내는 _value, 그리고 값을 표시해줄 Text component가 들어있다.

이 Tile sciprt를 UI Button에 추가하고, Button의 OnClick Listener에 Tile.OnClick()을 추가했다.

그리고 Prefab으로 저장.

 

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
public class Tile : MonoBehaviour
{
    public int x, y;
 
    private int _value;
    private Text _valueText;
 
 
    private void Start()
    {
        _valueText = GetComponentInChildren<Text>();
    }
 
    public void Initialize(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
 
    public void OnClick()
    {
        _value += 1;
 
        if (_valueText != null)
        {
            _valueText.text = _value.ToString();
        }
    }
}
 
cs

 

 

 

다음으로 Tile을 관리할 Board를 만들고, 

Tile Prefab을 width, height에 맞게 생성/배치한다.

 

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
public class Board : MonoBehaviour
{
    public int width, height;
    public GameObject tilePrefab;
    
    private Tile[,] _tiles;
    
    private void Start()
    {
        _tiles = new Tile[width, height];
        
        Initialize();
    }
 
    private void Initialize()
    {
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                var tileObject = Instantiate(tilePrefab, transform);
                var tile = tileObject.GetComponent<Tile>();
                tile.Initialize(x, y);
                tile.transform.localPosition = new Vector2(x * tile.GetComponent<RectTransform>().sizeDelta.x,
                    y * tile.GetComponent<RectTransform>().sizeDelta.y);
            }
        }
    }
}
cs

 

 

 

 

Board를 5*5로 생성한 결과

 

 

 

각 Tile을 클릭시 값이 +1된다.

 

 

 

 

 

<참고>

Code Monkey - https://youtu.be/waEsGu--9P8

반응형

'Unity & C#' 카테고리의 다른 글

Grid System (3) - A* Pathfinding  (0) 2020.05.30
Grid System (2) - 미로 만들기 (Maze Algorithm)  (0) 2020.05.22
Gyroscope Input (Unity Remote)  (0) 2020.05.10