안녕하세요 투니드입니다! 바로 시작할게요!!
이번에는 Marker(표시선? 화살표?) TileMap을 만들어 보도록 하겠습니다!
저희 상자를 표시해 주던 그 이미지 오브젝트 있잖아요?
이거요! 이걸 사용해서 만들 거라서 기존에 가지고 계시던걸 복사하셔서 사용하시면 됩니다!
복사는 필수는 아니구요, 저희 상자에 표시되는 사이즈를 개인의 기준에 맞춰서 조절했잖아요? 근데 타일맵으로 넣어버리면 사이즈가 또 좀 다를 수 있어서 사이즈 때문에 복사해서 쓰실 분들은 사용하시면 됩니다!
저는 사이즈가 너무 크게 나오길래 픽셀 퍼 유닛을 512로해서 사이즈를 확 줄였습니다!
아무튼! 이런식으로 사이즈를 조절하기 위해서는 먼저 타일맵으로 만들어봐야겠죠!
이렇게 기존 타일맵을 하나 복사해서 이름을 바꿔주고 그 안에 저는 타일까지 넣기는 했는데 마커를 넣어주면 됩니다!
넣는 방법은 전편에서 설명드렸으니 참고부탁드립니다!
넣고 나면 이런 식으로 씬에다가 마커를 마구 설치할 수 있어요 ㅋㅋㅋㅋㅋ
뭐 그냥 해봤습니다... 암튼 다시 지워주고요
기존 타일맵이 이미 있고 그 타일맵을 BackGround로 쓸 거라서, Layer에 값을 조절해서 표시순서를 맞춰주겠습니다!
Tilemap의 Inspector에서
이렇게 Order in Layer : -1로 설정해 줬습니다 왜냐면 숫자가 아래로 갈수록 빨리 그려지는 형태라서 배경뒤엔 뭐가 있을 필요가 없겠죠? 가장 먼저 그려져서 뒤로 그려지는 것들이 위로 올라오게끔 만들어줬습니다!
그러면 이제 스크립트로 넘어가겠습니다 MarkerTilemap 에다가 MarkerManager.cs 파일을 만들어서 붙여주겠습니다!
이 MarkerManager.cs가 하는 역할은 타일맵에다가 마커를 그려주는 역할을 할 거에요!
Update에서 항상 그려주게 만들어 줄 거라서, 이전위치와 현재위치가 같으면 실행하지 않게 한번 막아주고요!
SetTile() 내부함수를 이용해서 타일에 마커를 표시해 줄 건데, 마우스 위치를 계속 업데이트하면서 하나만 생성되게끔 만들어줬습니다!
만들어둔 참조변수를 할당해 줍니다!
이렇게 작업해주고 나서 ToolsCharacterController.cs 파일로 넘어갑니다!
ToolsCharacterController.cs 파일 기억나시나요? 현재는 간단하게 나무랑 상호작용을 하면 나무를 나뭇가지로 만드는 기능만 하고 있었어요!
여기에 이제 타일맵 마커를 어디에 그릴지 실질적인 위치를 계산해 줄 건데,
변수 두 가지 먼저 선언해 주고요!
Update()문에 Marker();를 넣어줍니다! Marker() 메서드는 저희가 만들었던 GetGridPosition()을 통해서
셀의 위치를 계산해서 MarkerManager.cs로 넘겨주는 역할을 해줄 겁니다!! 이렇게 작업해주고 나서
변수를 할당해 준 다음에! 확인을 해보면
이렇게 마우스를 따라다니는 마커를 생성했습니다!
이번 편에서 중요한 건 Layer 순서와 타일맵도 스크립트로 컨트롤할 수 있구나였던 것 같습니다! 처음 보는 기능들이고
어렵지만 그래도 재밌게 한 것 같아요!! 다음장에서 또 뵙겠습니다!
MarkerManager.cs
using UnityEngine.Tilemaps;
namespace MyStardewValleylikeGame
{
public class MarkerManager : MonoBehaviour
{
#region Variables
//마커를 표시할 타일맵
[SerializeField] Tilemap targetTilemap;
//마커로 사용할 타일
[SerializeField] TileBase tileBase;
//현재 마커가 위치할 타일맵 좌표(Vector3Int).
public Vector3Int markedCellPosition;
//이전 프레임에서 마커가 있던 위치를 저장하는 변수.
Vector3Int oldCellPosition;
#endregion
private void Update()
{
// 이전 위치와 현재 위치가 같으면 실행하지 않음
if (oldCellPosition == markedCellPosition) return;
Debug.Log("마커 위치: " + markedCellPosition);
//이전 위치(oldCellPosition)에 있던 마커를 제거 (null을 설정하면 타일이 삭제됨).
targetTilemap.SetTile(oldCellPosition, null);
//현재 위치(markedCellPosition)에 마커 타일(tileBase)을 배치.
targetTilemap.SetTile(markedCellPosition, tileBase);
//현재 위치를 oldCellPosition에 저장해서, 다음 프레임에서 이 위치의 타일을 지울 수 있도록 업데이트.
oldCellPosition = markedCellPosition;
}
}
}
ToolsCharacterController.cs
using UnityEngine;
namespace MyStardewValleylikeGame
{
// 캐릭터가 도구로 상호작용할 수 있도록 하는 컨트롤러 클래스
public class ToolsCharacterController : MonoBehaviour
{
#region Variables
// 캐릭터 컨트롤러 스크립트를 참조하는 변수
CharacterController2D character;
// Rigidbody2D 컴포넌트를 참조하는 변수
Rigidbody2D rgbd2d;
// 상호작용할 위치의 오프셋 거리
[SerializeField] float offsetDistance = 1f;
// 상호작용 가능한 영역의 크기
[SerializeField] float sizeOfInteractableArea = 1.2f;
// 마커 매니저를 참조하는 변수
[SerializeField] MarkerManager markerManager;
// 타일맵 리드 컨트롤러를 참조하는 변수
[SerializeField] TileMapReadController tileMapReadController;
#endregion
// 컴포넌트가 활성화될 때 호출되는 메서드
private void Awake()
{
// 캐릭터 컨트롤러와 Rigidbody2D 컴포넌트를 가져옴
character = GetComponent<CharacterController2D>();
// Rigidbody2D 컴포넌트를 가져옴
rgbd2d = GetComponent<Rigidbody2D>();
}
// 매 프레임마다 호출되는 메서드
private void Update()
{
// 마커 메서드 실행
Marker();
// 마우스 왼쪽 버튼이 눌렸을 때 도구 사용 메서드 실행
if (Input.GetMouseButtonDown(0))
{
UseTool();
}
}
// 마커를 표시하는 메서드
private void Marker()
{
// 마우스 위치에 따라 마커 위치를 설정
Vector3Int gridPosition = tileMapReadController.GetGridPosition(Input.mousePosition, true);
// 마커 매니저의 마커 위치를 설정
markerManager.markedCellPosition = gridPosition;
}
// 캐릭터가 도구를 사용하여 상호작용하는 메서드
private void UseTool()
{
// 캐릭터의 위치에서 오프셋 거리만큼 떨어진 위치를 계산
Vector2 position = rgbd2d.position + character.lastMotionVector * offsetDistance;
// 지정된 위치에서 상호작용 가능한 객체들을 감지
Collider2D[] colliders = Physics2D.OverlapCircleAll(position, sizeOfInteractableArea);
// 감지된 객체들 중에서 ToolHit 컴포넌트를 가진 객체를 찾음
foreach (Collider2D collider in colliders)
{
ToolHit hit = collider.GetComponent<ToolHit>();
// 객체가 ToolHit 컴포넌트를 가지고 있다면 Hit 메서드를 호출하고 반복문 종료
if (hit != null)
{
hit.Hit();
break;
}
}
}
}
}
TileData.cs
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
[CreateAssetMenu(menuName = "Data/Tile Data")]
public class TileData : ScriptableObject
{
public List<TileBase> tiles;
public bool plowable;
}
TileMapReadController.cs
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];
}
}
}
'StardewValleyLikeGameCloneCoding' 카테고리의 다른 글
Stardew Valley like Game in Unity Episode 9-2 Plowing and Seeding (0) | 2025.03.06 |
---|---|
Stardew Valley like Game in Unity Episode 9-1 Plowing and Seeding (0) | 2025.03.05 |
Stardew Valley like Game in Unity Episode 8-1 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 |