
다음에 구현해야할 기능은 게임 내에 무언가를 설치할 수 있는 기능이었다.
어떤 기능을 어디서부터 구현해야할지 감이 잡히지 않아 자료를 찾아보던 도중 다음 동영상을 발견했다.
https://youtu.be/gFpmJtO0NT4?si=nD14fEcY7GUsw2PG
해당 영상에서 다루는 것은 Isometric Tilemap 기반이지만, 진행중인 Rectangular Tilemap에 맞춰 변형할 경우 큰 도움이 될 것이라고 판단했다.
우선 해당 동영상을 따라하며 기능을 이해하고, 현재 진행중인 프로젝트에 맞춰 코드를 개선하는 것이 좋을 것이라고 생각했다.
영상에서 구현한 기능은 크게 나눈다면 다음과 같다.
1. 구조물이 생성됨.
2. 구조물이 이동함.
3. 이동한 위치에 건설이 가능하다면 녹색타일, 아니면 적색타일을 구조물 위치에 띄움
4. 특정 키를 누르면 건물이 설치되거나 사라짐
1번부터 차례대로 분석을 해볼 예정이다.
코드를 보여줘야할 경우, 코드 블록에 필요한 메서드를 표시할 것이며, 필요할 경우 필드나 프로퍼티까지만 표시할 예정이다.
우선 지속적으로 나올 Building 클래스의 경우 다음과 같다.
public class Building : MonoBehaviour
{
public bool placed { get; private set; }
public BoundsInt area;
public bool CanBePlaced()
{
Vector3Int positionInt = BuildingSystem.instance.gridLayout.LocalToCell(transform.position);
BoundsInt areaTemp = area;
areaTemp.position = positionInt;
if (BuildingSystem.instance.CanTakeArea(areaTemp))
{
return true;
}
return false;
}
public void Place()
{
Vector3Int positionInt = BuildingSystem.instance.gridLayout.LocalToCell(transform.position);
BoundsInt areaTemp = area;
areaTemp.position = positionInt;
placed = true;
BuildingSystem.instance.TakeArea(areaTemp);
}
}
1. 구조물 생성
구조물을 생성하는 기능의 경우 다음 메서드를 버튼에 연결하여 사용했다.
private Building temp;
public void InitializeWithBuilding(GameObject building)
{
temp = Instantiate(building, Vector3.zero, Quaternion.identity).GetComponent<Building>();
FollowBuilding();
}

생성할 때 Instantiate메서드를 이용해 오브젝트를 생성했다.
만약 개선한다면 오브젝트풀을 이용한 방식으로 만들 수도 있을 것 같다.
또한 예시에서는 Building의 BoundsInt
2. 구조물 이동, 3. 녹색타일 적색타일 표시
FollowBuilding()은 다음과 같은 메서드이다.
private void FollowBuiling()
{
ClearArea();
temp.area.position = gridLayout.WorldToCell(temp.gameObject.transform.position);
BoundsInt buildingArea = temp.area;
TileBase[] baseArray = GetTileBlock(buildingArea, MainTilemap);
int size = baseArray.Length;
TileBase[] tileArray = new TileBase[size];
for (int i = 0; i < baseArray.Length; i++)
{
if (baseArray[i] == _tileBases[1])
{
tileArray[i] = _tileBases[2];
}
else
{
FillTiles(tileArray, 3);
break;
}
}
TempTilemap.SetTilesBlock(buildingArea, tileArray);
prevArea = buildingArea;
}
// 타일 배열 반환 메서드
private TileBase[] GetTileBlock(BoundsInt area, Tilemap tilemap)
{
TileBase[] array = new TileBase[area.size.x * area.size.y * area.size.z];
int counter = 0;
foreach (Vector3Int v in area.allPositionsWithin)
{
Vector3Int pos = new Vector3Int(v.x, v.y, 0);
array[counter] = tilemap.GetTile(pos);
counter++;
}
return array;
}
// 타일 설정하는 메서드
private void SetTilesBlock(BoundsInt area, int n, Tilemap tilemap)
{
int size = area.size.x * area.size.y * area.size.z;
TileBase[] tileArray = new TileBase[size];
FillTiles(tileArray, n);
tilemap.SetTilesBlock(area, tileArray);
}
// 타일 채우는 메서드
private void FillTiles(TileBase[] p_arr, int p_n)
{
for (int i = 0; i < p_arr.Length; i++)
{
p_arr[i] = _tileBases[p_n];
}
}
영상에서는 좀 더 직관적으로 알 수 있도록, 열거형을 Key 값으로 하는 딕셔너리를 이용했지만, 내가 따라할 때는 단순 배열로 이용했다.
FollowBuilding은 구체적으로는 건물 하단의 설치 가능한 타일을 표시해주는 역할을 하는 부분이다.
반복문 부분은 설치되려는 부분이 _tileBases[1](설치 가능한 타일)이면 _tileBases[2](녹색타일)을 표시하고, 그렇지 않다면 FillTiles을 통해 모든 타일을 _tileBases[2](적색타일)을 표시한다.
if (Input.GetMouseButtonDown(0))
{
if (EventSystem.current.IsPointerOverGameObject(0))
{
return;
}
if (!temp.placed)
{
Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3Int cellPosition = gridLayout.LocalToCell(mousePosition);
if (prevPos != cellPosition)
{
temp.transform.localPosition = gridLayout.CellToLocalInterpolated(cellPosition);
prevPos = cellPosition;
FollowBuilding();
}
}
}
FollowBuilding은 클릭시에도 작동하는데, 이때 클릭한 위치로 Building의 오브젝트를 이동한다.
설치는 스페이스바를 누르면 작동하고, ESC버튼을 통해 생성한 오브젝트를 지우게 했다.
else if(Input.GetKeyDown(KeyCode.Space))
{
if(temp.CanBePlaced())
{
temp.Place();
}
}
else if(Input.GetKeyDown(KeyCode.Escape))
{
ClearArea();
Destroy(temp.gameObject);
}
설치는 Building의 Place()메서드로 진행된다.
'내일배움캠프 TIL' 카테고리의 다른 글
| 내일배움캠프 64일차 TIL "foreach문 중의 수정" (0) | 2024.12.17 |
|---|---|
| 내일배움캠프 63일차 TIL "프로젝트 중간 점검" (0) | 2024.12.16 |
| 내일배움캠프 61일차 TIL "커스텀 에디터 기능" (0) | 2024.12.12 |
| 내일배움캠프 60일차 TIL "데이터 로드시 버그 수정" (0) | 2024.12.11 |
| 내일배움캠프 59일차 TIL "작물이 두번 설치되던 현상" (0) | 2024.12.10 |