안녕하세요! 투니드입니다!
이번 편에서는 타일맵과 Marker라고 되어있는데요! 이번편부터 몇 편간은 유튜브의 자동자막이 막혀있어서,
영상을 보면서 듣긴 듣고, 따라하면서 최대한 설명을 해보긴 할 텐데, 조금 모자랄 수도 있는 점 양해부탁드리겠습니다 ㅠ ㅠ
저도 알아듣고싶고 설명하고 싶어요 ㅠㅠ.... (영어 공부를 확실히 해야겠긴 합니다 ㅠㅠ)
아무튼 시작해보죠!
이번 편에서는 농사가 가능한 땅과 불가능한 땅을 스크립터블 오브젝트와 타일맵 기능을 이용해서 구분을 지어줄 거에요!
저희가 이 프로젝트를 시작할 즈음 만들고 시작했던 팔레트데이터 있죠? 그걸 전부 날려주면 됩니다 OverworldPalette폴더 안에 있는 데이터들을 전부 날려주고(스크린샷 안에 2개 남은 건 새로 만든 거에요!)
타일맵 안에 있는 데이터 역시 지워줘야하는데, 타일맵안에있는 데이터를 지우는 방법은 1번을 먼저 누르고 2번 지우개를 눌러서 안에있는 데이터를 쭉쭉 지워주시면 됩니다!
그리고 나서 저희 Overworld Sprite파일 있죠? 거길로 갑니다!
여기서 SpriteEditor를 눌러준 다음에
맨 위에 맨 왼쪽에 있는 스프라이트를 잡아서 Grass라고 지정해 줬고 엔터 쳐주시고요
왼쪽 맨 아래에 보시면 풀들에 둘러싸인 흙이 있어요! 그걸 PlowableDirt(농사 가능한 흙) 이라고 지어주고 엔터 쳐준다음 Apply 해주시면 됩니다!
그러면 이제
이런 식으로 밑에 생기게돼요! (PlowableDirt는 엄청 아래에 있습니다)
그럼 이걸 초기화한 타일맵에다가 넣어줄 거에요! 어떻게 넣냐면
Grass랑 PlowableDirt를 드래그해서 OverworldPalette에다가 갖다 놓으면 파일 저장하는 창이 뜹니다! 거기서
이렇게 저장시키고 초기화했던 폴더로 가져온 거에요!
와 이거 어떻게 설명해야 할지 한참을 고민했었는데 잘 이해가 된다면 좋겠습니다...
이렇게 만들었으면! 스크립트 파일을 하나 만들어줍니다
TileData.cs 파일을 만들고 스크립터블 오브젝트로 만들어줍니다! 그리고 여기서 TileBase라는 새로운 타입이 나오는데,
이거는 저도 계속 보면서 나중에 설명을 드려볼게요!
아무튼 TileBase는 정확히는 타일맵 안에 있는 데이터를 참조할 수 있는 변수타입이라고 생각하면 될 것 같더라구요
그리고 plowable은 말 그대로 농사가 가능한지 여부를 체크하는 거구요!
이렇게 저장한 다음에
스크립터블 오브젝트의 새로운 유형이 생겼으니 폴더링을 새로 해줬습니다!
농사가 가능한 땅과 불가능한 땅 2개의 유형의 스크립터블 오브젝트를 생성해 주고
Not 에는 Plowable 비체크, 아까 만들었던 팔레트 데이터중 Grass를 Tiles에 할당시켜 줍니다!
그리고 반대로 Plowable에는 Plowable 당연히 체크, PlowableDirt를 할당시켜 주면 됩니다!
할당을 시켜줬다면 이제 GameManger로 가서 TileMapReadController.cs 파일을 하나 만들어주겠습니다
먼저 타일맵 변수를 직렬화해서 하나 만들어주고
TileBase를 반환하는 GetTileBase메서드를 만들어줍니다 이 GetTileBase()는 결국
마우스의 위치를 가져와서 마우스 위치에 있는 타일이 어떤 타일인지 보여주는 메서드라고 보시면 됩니다!
저희가 Interactable(상호작용)을 할 때는 Collider나 이런 걸로 상호작용을 했었는데, 2D 프로젝트의 타일맵에는
콜라이더가 없죠 그래서 이렇게 Tilemap과 직접 상호작용을 할 수 있게 만들어야 합니다!
이것을 실행시켜 보면
원활한 테스트를 위해서 클릭할 때만 디버그를 찍어봤어요! 그러면 Grass(NotPlowable) 인지 PlowableDirt인지 마우스 포지션을 기반으로 확인할 수 있게 됐습니다!
네 그러면 이제부터 조금 복잡해집니다.... 디버그로 타일의 포지션과 이게 어떤 타일인지까지 찍어봤어요!
근데 타일들이 이 두 가지만 쓰이는 게 아니라 여러 가지가 쓰이겠죠? 그걸 전부 다 처리해 주기 위해서
딕셔너리와 List를 하나씩 사용할 겁니다!
tileData는 직렬화해서 나중에 타일로 쓰일 스크립터블 오브젝트들을 전부 넣어주면 되고요!
Start() 메서드입니다 먼저 딕셔너리를 초기화하고 TileData 안에 TileBase는
1번이 TIleData고 2번이 TileBase입니다 이해가 되시나요??
그리고 그 밑에 코드로는 접은 글로 먼저 적을게요
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
namespace MyStardewValleylikeGame
{
public class TileMapReadController : MonoBehaviour
{
#region Variables
// Tilemap 컴포넌트 참조 (Unity 에디터에서 할당)
[SerializeField] Tilemap tilemap;
// 여러 개의 TileData를 저장하는 리스트 (Unity 에디터에서 할당)
[SerializeField] List<TileData> tileData;
// 특정 TileBase에 매칭되는 TileData를 빠르게 조회하기 위한 딕셔너리
Dictionary<TileBase, TileData> dataFromTiles;
#endregion
private void Start()
{
// 딕셔너리 초기화 (타일-데이터 매핑을 저장할 공간 생성)
dataFromTiles = new Dictionary<TileBase, TileData>();
// tileData 리스트를 순회하며 각 타일과 연결된 데이터를 딕셔너리에 저장
foreach (TileData tiledata in tileData)
{
foreach (TileBase tileBase in tiledata.tiles) // 해당 TileData에 포함된 모든 타일을 가져옴
{
dataFromTiles.Add(tileBase, tiledata); // 타일을 키로, TileData를 값으로 저장
}
}
}
private void Update()
{
// 마우스 왼쪽 버튼을 클릭하면 해당 위치의 타일 정보를 가져옴
if (Input.GetMouseButtonDown(0))
{
GetTileData(GetTileBase(GetGridPosition(Input.mousePosition, true)));
}
}
/// <summary>
/// 주어진 화면 좌표 또는 월드 좌표를 그리드 좌표(Vector3Int)로 변환
/// </summary>
/// <param name="position">변환할 좌표 (화면 좌표 또는 월드 좌표)</param>
/// <param name="mousePosition">true면 마우스 좌표를, false면 월드 좌표를 변환</param>
/// <returns>그리드 셀 위치 (Vector3Int)</returns>
public Vector3Int GetGridPosition(Vector2 position, bool mousePosition = false)
{
Vector3 worldPosition;
if (mousePosition)
{
// 마우스 화면 좌표를 월드 좌표로 변환
worldPosition = Camera.main.ScreenToWorldPoint(position);
}
else
{
// 이미 월드 좌표가 주어진 경우 그대로 사용
worldPosition = position;
}
// 월드 좌표를 타일맵의 그리드 셀 좌표로 변환
Vector3Int gridPosition = tilemap.WorldToCell(worldPosition);
Debug.Log("gridPosition = " + gridPosition); // 변환된 좌표를 로그로 출력
return gridPosition;
}
/// <summary>
/// 주어진 그리드 위치에 있는 타일을 반환
/// </summary>
/// <param name="gridPosition">그리드 셀 좌표 (Vector3Int)</param>
/// <returns>해당 위치의 TileBase (없으면 null)</returns>
public TileBase GetTileBase(Vector3Int gridPosition)
{
// 타일맵에서 주어진 위치의 타일을 가져옴
TileBase tile = tilemap.GetTile(gridPosition);
Debug.Log("TileBase is " + tile); // 찾은 타일 정보를 로그로 출력
return tile;
}
/// <summary>
/// 주어진 타일에 해당하는 TileData를 반환
/// </summary>
/// <param name="tileBase">찾고 싶은 TileBase</param>
/// <returns>TileBase에 해당하는 TileData</returns>
public TileData GetTileData(TileBase tileBase)
{
// 딕셔너리에서 해당 타일의 데이터를 가져옴
Debug.Log("TileData is " + dataFromTiles[tileBase]); // 검색된 데이터 로그 출력
return dataFromTiles[tileBase];
}
}
}
저도 처음 보는 형식들이고 어려워서 GPT를 최대한 활용하고 계속 번갈아보면서 주석을 달았습니다 이걸 보시는 게 이해가 훨씬 잘되실 거예요! 그리고 디버그도 각 메서드마다 찍어놨기 때문에 실행하면서 보면 이해가 팍팍될 겁니다!
결국은
타일의 위치값이 어딘지 이게 무슨 타일인지 농사가 가능한지 여부를 판단하는 클래스에요!
이러면 이제 저희가 농사가 가능한 땅과 불가능한 땅 정도는 구분을 해냈습니다!!!
아 참! 그리고 GameManager Object에서
스크립터블 오브젝트 2개 만든 거 둘 다 넣어주셔야 합니다!!!
그럼 또 다음편에서 계속하겠습니다!
'StardewValleyLikeGameCloneCoding' 카테고리의 다른 글
Stardew Valley like Game in Unity Episode 9-1 Plowing and Seeding (0) | 2025.03.05 |
---|---|
Stardew Valley like Game in Unity Episode 8-2 Tilemap and Marker (0) | 2025.03.05 |
Stardew Valley like Game in Unity Episode 7-3-1 Toolbar (0) | 2025.03.05 |
Stardew Valley like Game in Unity Episode 7-3 Toolbar (0) | 2025.03.04 |
Stardew Valley like Game in Unity Episode 7-2 Toolbar (0) | 2025.03.04 |