미니게임 제작 14
앞으로는 간단한 게임들을 만들어보며 추가적인 기능에 대해 공부를 해보려한다. 간단한 것부터 만들기 시작하여 만든 결과물을 레퍼런스 하여 덩치를 조금씩 키워나가는 과정을 밟아보자. 지식이 많지 않아 부족할 수 있지만, 하는데까지 해보겠다.
현재 구상 하고 있는 것은 예전에 잠깐 화제가 되었던 모바일 게임 매직 서바이벌 과 스팀에서 최근 붐이 일었던 게임 뱀파이어 서바이벌 의 장르를 본딴 생존 서바이벌 슈팅 게임이다.
이번에는 플레이어가 이동함에 따라서 맵 타일을 이동시켜 무한 맵을 구현해보겠다.
일단 코드를 먼저 보자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class BgScrolling : MonoBehaviour
{
public GameObject[] tmp_tile; //임시 타일 public으로 받기
public GameObject[,] tile; //임시 타일을 3x3으로 바꿀 변수
private int currentIndex_i; //현재 나의 타일 인덱스 i
private int currentIndex_j; //현재 나의 타일 인덱스 j
private string tmpStringIndex; //오브젝트 이름(ex. 00 ~ 22)로 받을 변수
private void Start()
{
tile = new GameObject[3, 3]; // 3x3
int cnt = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
tile[i, j] = tmp_tile[cnt]; //타일을 2차원으로 변경
cnt += 1;
}
}
tmpStringIndex = this.name; //오브젝트 이름을 스트링으로 받아서 인덱스에 넣음
currentIndex_i = int.Parse(tmpStringIndex[0].ToString());
currentIndex_j = int.Parse(tmpStringIndex[1].ToString());
}
private void OnTriggerExit2D(Collider2D other) //충돌 Exit처리 -> 나가면 배경이 바뀌어야 함
{
if (other.tag != "Player") return; //다른 충돌이면 그냥 리턴
Vector3 dir = other.transform.position - transform.position; //플레이어의 위치 - 타일의 중심 =>>> 타일 중심에서의 벡터가 나옴
float angle = Vector3.Angle(transform.up, dir); //각도
int sign = Vector3.Cross(transform.up, dir).z < 0 ? -1 : 1;
angle *= sign;
if (-45 <= angle && angle <= 45) // 위쪽
{
for (int i = 0; i < 3; i++) // 타일 3개를 옮겨야 함
{
if (currentIndex_i + 1 <= 2) // 배열에 대한 예외처리, 아래의 else문은 currentIndex_i가 2일때임
{
if (tile[currentIndex_i + 1, i].transform.localPosition.y - transform.localPosition.y == -16)
{
tile[currentIndex_i + 1, i].transform.localPosition += new Vector3(0, 16 * 3, 0); //위쪽으로 가므로 아래행을 옮김
}
}
else
{
if (tile[0, i].transform.localPosition.y - transform.localPosition.y == -16) //currentIndex_i가 2일때는 아래가 0인덱스
{
tile[0, i].transform.localPosition += new Vector3(0, 16 * 3, 0);
}
}
}
}
else if (45 <= angle && angle <= 135) // 왼쪽
{
for (int i = 0; i < 3; i++)
{
if (currentIndex_j + 1 <= 2)
{
if (tile[i, currentIndex_j + 1].transform.localPosition.x - transform.localPosition.x == 17)
{
tile[i, currentIndex_j + 1].transform.localPosition += new Vector3(-17 * 3, 0, 0);
}
}
else
{
if (tile[i, 0].transform.localPosition.x - transform.localPosition.x == 17)
{
tile[i, 0].transform.localPosition += new Vector3(-17 * 3, 0, 0);
}
}
}
}
else if (135 <= angle || -135 >= angle) // 아래쪽 -135 ~ -180 or 135 ~ 180
{
for (int i = 0; i < 3; i++)
{
if (currentIndex_i - 1 >= 0)
{
if (tile[currentIndex_i - 1, i].transform.localPosition.y - transform.localPosition.y == 16)
{
tile[currentIndex_i - 1, i].transform.localPosition += new Vector3(0, -16 * 3, 0);
}
}
else
{
if (tile[2, i].transform.localPosition.y - transform.localPosition.y == 16)
{
tile[2, i].transform.localPosition += new Vector3(0, -16 * 3, 0);
}
}
}
}
else if (-135 <= angle && angle <= -45) // 오른쪽
{
for (int i = 0; i < 3; i++)
{
if (currentIndex_j - 1 >= 0)
{
if (tile[i, currentIndex_j - 1].transform.localPosition.x - transform.localPosition.x == -17)
{
tile[i, currentIndex_j - 1].transform.localPosition += new Vector3(17 * 3, 0, 0);
}
}
else
{
if (tile[i, 2].transform.localPosition.x - transform.localPosition.x == -17)
{
tile[i, 2].transform.localPosition += new Vector3(17 * 3, 0, 0);
}
}
}
}
}
}
횡스크롤 배경을 무한 스크롤링 하는 것은 간단했지만, 탑뷰를 기준으로 무한 맵을 만드는 방법은 아무리 고민해봐도 생각이 나지 않았다. 따라서 구글링을 통해 방법을 찾아보았고, 위 링크에 있는 코드를 내 프로젝트에 맞게 변형하여 사용하였다.
요점은 다음과 같다. 전체 Map 타일을 3*3으로 나눈다. 각각의 나뉘어진 타일은 Collider2D 컴포넌트를 가지고 있고, isTrigger가 체크되어 있다.
각각의 OnTriggerExit2D 메서드를 통해 현재 타일에서 벗어났을 경우, 그 각도를 체크한다.
각도에 따라서 아래, 위, 오른쪽, 왼쪽 타일을 이동시킨다.
영상으로 보면 어떻게 이루어지는 지 더 잘 보일 것이다.
위 Gif 파일을 통해서 보면, 플레이어가 이동하는 방향에 따라 9분할된 Map 타일이 당겨지는 모습을 볼 수 있다.
게임 화면에선 다음과 같이 나타난다. 이유를 모르겠지만, 오른쪽에 분명히 타일 맵이 깔려 있는데도 위 그림처럼 로딩이 되지 않아 빈 공간이 나타나는 모습이다. 이것 저것 해결 방법을 시도했지만 아직 해결하지 못한 상태다.
약간 석연찮은 점은 있지만, 무한 맵을 마지막으로 이번 실습에서 구현하고 싶었던 부분은 모두 구현완료 했다.
다음에는 지금까지 어떤 내용을 구현했는지 정리해보겠다.