저번 개발 과정에서 어떤 작업을 했는지 리뷰해보자.
맵을 만들기 위해 타일 형식으로 맵을 만들 것인데 타일 에셋을 만들어주기 위해 Project 창에서 +를 누른 후 2D > Tiles > Rule Tile 으로 타일 에셋을 생성해준다. 이 때 타일의 이름을 Ran Tile로 설정해준다.
위와 같이 Size를 10으로 설정하고 Sprite를 채워줬다.
인스펙터창의 오른쪽 위의 자물쇠를 잠구면 다른 스프라이트를 누르거나 오브젝트를 눌러도 인스펙터 창이 변하지 않고 그대로 유지된다.
인스펙터 창이 아니어도 다른 창에서도 동일하게 사용 가능하다.
완성된 타일 에셋을 팔레트에 드래그드랍하여 덮어씌운다.
Window > 2D > Tile Palette로 팔레트 창을 열어줄 수 있다.
하이어라키에서 2D Object > TileMap > Rectangular을 선택해서 생성해준다. 이후에 팔레트 아래에서 Default Brush를 Line Brush로 변경해주고 팔레트의 타일을 한 번 클릭하면 타일을 그릴 수 있게 마우스 모양이 변한다.
팔레트 상단의 아이콘이 붓으로 설정된 상태여야 한다.
그 상태에서 게임 씬에서 다음과 같이 플레이어를 중심으로 20x20 사각형을 그려준다. 다 그린 후에는 다시 Default Brush로 변경한다.
이후에 팔레트의 페인트 통 툴을 선택 + 잔디 타일을 선택한 다음 빈 공간을 클릭하면 모든 빈 공간이 선택한 타일로 채워진다.
플레이어가 멀어지면 플레이어의 진행 방향으로 타일을 재배치해서 맵이 끊기지 않도록, 계속해서 맵이 있도록 재배치 이벤트를 추가할 것이다. 이 때 재배치 이벤트를 구현하기 위해선 다음과 같은 과정이 필요하다.
Repostion, GameManager이라는 이름으로 C# 스크립트를 하나씩 생성해준다.
타일맵 오브젝트에 Reposition 스크립트를 컴포넌트로 추가해준다. 이 때 타일맵이 플레이어 정보를 얻어와야하는데 플레이어의 정보같은 핵심 정보는 GameManager에 구현해서 다른 여러 스크립트에서 사용가능하도록 구현하는 것이 좋다.
게임매니저를 담당할 오브젝트를 GameManager 오브젝트를 추가한 후 GameManager 스크립트를 컴포넌트로 추가한다.
public Player player;
다음과 같이 게임 매니저에 Player를 선언하면 인스펙터의 스크립트 컴포넌트 부분에 플레이어 변수에 Player 오브젝트를 드래그드랍해서 초기화하였다.
그 다음 다른 스크립트에서 게임 매니저를 접근할 수 있도록 메모리에 게임 매니저를 얹는다.
장면이 하나라서 싱글톤 로직을 사용하지는 않는다.
public static GameManager Instance;
void Awake()
{
//static은 인스턴스에 나오지 않으므로 초기화 해줘야함
Instance = this;
}
다음과 같이 정적 변수로 Gamamager를 선언하면 다른 스크립트의 클래스에서 부를 수 있다는 편리함이 있다.
다음과 같이 Reposition 스크립트를 작성했다. 코드가 어떤 기능을 하고 왜 그렇게 작성했는지에 대해 주석을 작성해놓았다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Reposition : MonoBehaviour
{
//Trigger가 check된 collider에서 나갔을때 호출
void OnTriggerExit2D(Collider2D collision)
{
if(!collision.CompareTag("Area")) //나간 Collision의 Tag가 Area가 아니면 바로 return
return;
//Player의 위치를 가져옴
Vector3 playerPos = GameManager.Instance.player.transform.position;
//내 위치를 가져옴
Vector3 myPos = transform.position;
float diffX = Mathf.Abs(playerPos.x - myPos.x); //x축 좌표 차이
float diffY = Mathf.Abs(playerPos.y - myPos.y); //y축 좌표 차이
//플레이어의 방향을 파악
Vector3 playerDir = GameManager.Instance.player.inputVec;
float dirX = playerDir.x < 0 ? -1 : 1; //player의 inputVec의 x가 음수이다? 진행방이 왼쪽(-1), 아닐경우 오른쪽(1)
float dirY = playerDir.y < 0 ? -1 : 1; //player의 inputVec의 y가 음수이다? 진행방이 아래쪽(-1), 아닐경우 위쪽(1)
//collsion이 어떤 태그이냐에 따라 동작이 다름
//추후에 몬스터도 재배치를 해주기 위해 설정
switch (transform.tag)
{
case "Ground": //collsion의 태그가 ground일 경우
if ( Mathf.Abs(diffX - diffY) <= 0.1f) { // 모서리 부분에서 그라운드 이동이 정상적이지 않은 오류를 보완하기 위한 코드
transform.Translate(Vector3.right * dirX * 40);
transform.Translate(Vector3.up * dirY * 40);
}
else if (diffX > diffY) //두 오브젝트의 거리 차이에서 X축이 Y축보다 크면 맵을 수평이동
{
//Translate 지정된 값 만큼 현재 위치에서 이동
transform.Translate(Vector3.right * dirX * 40); //오른쪽 단위 벡터(1, 0, 0) * 방향(왼쪽 -1 , 오른쪽 1) * 크기(40)
//크기가 40인 이유는 타일맵을 4개를 사용해서 2*2로 설정했기 때문
}
else if (diffX < diffY) //두 오브젝트의 거리 차이에서 Y축이 X축보다 크면 맵을 수평이동
{
//Translate 지정된 값 만큼 현재 위치에서 이동
transform.Translate(Vector3.up * dirY * 40);
}
break;
case "Enemy": //collsion의 태그가 Enemy일 경우
break;
}
}
}
타일맵 선택한 후 Ctrl+D를 사용해서 3개를 복사해준 후 2x2로 배치해준다.
Scene 창의 Snapping을 10으로 설정한 후 Ctrl + 기즈모 드래그를 하면 10씩 오브젝트가 이동한다.
메인 카메라에 Pixel Perfect Camera 컴포넌트를 추가
타일맵 크기, Area 크기, 재배치 거리는 카메라 크기와 비슷하게 설정한다.
패키지 매니저에서 Chinemachine 패키지를 설치해준다. 그런 다음 하이어라키에서 Chinemachine > Virtual Camera를 생성해준다. 이 Virtual Camera가 메인 카메라의 감독 역할을 한다고 생각하면 된다.
Virutal Camera 오브젝터 인스펙터의 Follow에 플레이어를 할당하면 플레이어를 따라다니면서 카메라가 움직인다.