첫번째로 지렁이 2.5d top down 게임을 개발하기로 했다.
어떤 게임인지 우선 설명하자면 이렇다.
1. 지렁이가 땅에 랜덤으로 떨어지는 먹이를 먹으면 몸이 늘어나고(레벨증가) , 장애물에 부딪히면 몸이 줄어든다.(레벨감소)
2. 지렁이가 땅에 랜덤으로 떨어지는 골드를 먹으면 '상점'에서 여러가지 버프와, 갑옷 구매가 가능하다.
3. 지렁이의 몸이 특정 레벨까지 오르면 게임 클리어
4. 지렁이의 몸이 모두 사라지면 게임 오버
[계획]
끝없이 늘어나는 맵
몸집이 늘어나는 지렁이
랜덤 아이템 스폰
상호작용 UI
오늘은 계획 중 첫번째인 맵 생성을 해볼 예정이다.
처음엔 이런 여러가지 방법을 생각해보았다.
1. 미리 모두 씬에 생성해놓기
1-1. 시작시 2중배열을 활용하여 넓고 크게 생성
2. 오픈월드?
3. 땅을 롤링하여 움직이는 느낌만 나게만들기
1,1-1번은 맵크기가 커질수록 필요한 파일이 늘어났다.
가지 않을 수도 있는 곳까지 미리 만들어놔야하며, 만약 플레이어가 맵의 끝에 도달하게 된다면 게임을 즐기는 것에 방해가 될 수 있다
2번의 오픈월드는 아예 감이 안와서,,유니티 공식 유튜브에 올라온 영상을 보았다
맨처음 나오는 오픈월드의 조건에
1. 긴 가시거리 : 탑뷰로 진행하는 이 게임과 맞지않음
2. 연결된 빅사이즈 월드 : 미리 생성해놔야하는 듯 하다.. 한장의 이미지로 배경을 만드려는 이 개발에는 잘 안맞는듯함..!
3. 프리카메라 360도 : 탑뷰로 고정시켜져있으므로 이 게임과 맞지않음
4. 백로딩 : 정확히는 이해못한듯하나.. 가시영역안의 것들만 랜더링을 하고, 나머지는 데이터로 남겨두는 것을 말하는 듯 하다.. 역시 이 게임에서 구현하기엔 아까운 느낌.
이 게임 개발과는 맞지않는다고 느꼈다. 생각하던 것과 거리가 있는 기능이다....! 패스!
https://www.youtube.com/watch?v=pQ0lb9OxxbE
..그렇기에 3번의 롤링이 가장 괜찮아 보였다.
단 몇장의 사진 만으로도 아무리 움직여도 끝이 없는 (오픈월드같은)맵를 흉내낼 수 있을 것 같다.
땅 이미지가 한장 뿐인 지금 내가 할 수 있는 방법은 무엇이 있을까?
적어도 화면의 4배 크기 분량의 이미지를 사용하여 이동 반대 방향으로 움직이게 만들고,
카메라의 각 끝점이 현재 지렁이가 서있는 이미지를 넘어 가게된다면, 이동 반대 방향에 있던 이미지들이 다시 이동 방향쪽으로 위치를 변경하는 방법을 우선 생각해보았다.
이 방법은 카메라의 자식으로 맵을 놓고 n개의 맵이 이동 방향을 입력받아 이동 반대 방향으로 롤링되는 방식이다
여러개의 맵이미지를 이용하여 처음 카메라의 위치를 기준으로
[맵이미지의 사이즈보다 더 나아가면] 그 반대쪽의 이미지 Destroy 또는 배열을 활용하여 그 배열의 이미지를 이동방향쪽으로 이동시킨후, 다시 나아간 거리를 초기화 하는 방식으로 가능할 것 같다!
그런데 순간 아차싶었다. 나는 왜 쉬운길을 놔두고 돌아가려고 했을까!
비슷한 방식이지만, 카메라(=지렁이)가 특정 좌표만큼 움직일때 다시 그 자리에 맵을 가져오게 만들면, 땅을 움직이게 할 필요가 없어서 더 쉽지않나!
실제 위치를 움직이기 때문에 랜덤으로 넣어질 먹이와 골드 생성에도 이 방법이 훨씬 좋을 것 같다.
(위의 방법을 사용했다면 생성된 모든 오브젝트들은 맵과 같이 움직이고 지렁이는 가만히 있는 형태 였을 것이다..)
(다시보니 그냥 분리하면 되는 것 이었다. 하지만 생성과 삭제를 너무 많이 하는 것은 안좋으니 좋은 방식을 선택한 것 같다.)
결론 : input시스템으로 지렁이를 움직이게 만들고, 시작시 4*4사이즈의 맵을 생성, 맵 가운데에서부터 시작하여, offset값(이미지의 크기)만큼 벗어날때 바로 그 위치에 맵 중앙의 위치를 옮긴다.
> 우선 기초가 될 맵 자체를 생성해 준다.
프로젝트 실행시 2중for문을 활용하여 맵을 캔버스(UI)에 Instantiate해준다.
public class MapTile : MonoBehaviour
{
//맵타일 프리팹
public GameObject mapTilePrefab;
//맵 개수
[SerializeField] private int mapTileX = 4;
[SerializeField] private int mapTileY = 4;
//이 캔버스의 위치정보
private RectTransform thisRect;
void Start()
{
thisRect = GetComponent<RectTransform>();
for (int y = 0; y < mapTileY; y++)
{
for (int x = 0; x < mapTileX; x++)
{
Instantiate(mapTilePrefab, thisRect);
}
}
}
> 맵이 특정 위치(저장된 전 위치에서 offset만큼 떨어진 위치)에 도달했는지 체크하는 매서드
프로젝트 실행시 현재 카메라의 위치( = 플레이어의 위치 ) 를 기준 위치에 저장한다.
매프레임마다 카메라의 X와 Z의 이동거리인 현재의 위치 - 기준 위치를 계산한다.
만약 카메라의 X와 Z의 이동거리가 맵 사이즈와 같아지면 true를 반환하는 메서드
//[맵생성부분생략]
//참조할 카메라
public Transform cameraTransform;
//이 캔버스의 위치정보
private RectTransform thisRect;
//맵 사이즈 (:간격)에 따라 이동
[SerializeField] private float offset = 10f;
//비교대상 - 전위치, 기준이 되는 위치
private float camerabeforePosX;
private float camerabeforePosZ;
//카메라의 이동거리 - 매프레임 업데이트
private float cameradisX;
private float cameradisZ;
void Start()
{
thisRect = GetComponent<RectTransform>();
//시작 카메라 위치 저장
camerabeforePosX = cameraTransform.position.x;
camerabeforePosZ = cameraTransform.position.z;
}
private void Update()
{
//이동거리 = 현재위치 - 이전 위치
cameradisX = cameraTransform.position.x - camerabeforePosX;
cameradisZ = cameraTransform.position.z - camerabeforePosZ;
}
//이동거리가 offset이상이라면
private bool MapChecking()
{
if (cameradisX >= offset || cameradisX <= -offset || cameradisZ >= offset || cameradisZ <= -offset)
return true;
else
return false;
}
> 특정거리 도달시 현재 위치로 Canvas를 이동시키는 함수생성 후 완성
thisPos에 Canvas의 현재위치를 받아와 이동 거리(offset)만큼 더해준후 적용한다.
//[맵생성부분생략]
//[이동거리체크부분생략]
private void Update()
{
if (MapChecking())
{
//맵 이동
MapMoving();
}
}
private void MapMoving()
{
//캔버스의 현재위치
Vector3 thisPos = thisRect.position;
if (cameradisX >= offset)
{
thisPos.x += offset;
//이전위치 = 현재위치 저장
camerabeforePosX = cameraTransform.position.x;
}
else if (cameradisX <= -offset)
{
thisPos.x -= offset;
camerabeforePosX = cameraTransform.position.x;
}
if (cameradisZ >= offset)
{
thisPos.z += offset;
camerabeforePosZ = cameraTransform.position.z;
}
else if (cameradisZ <= -offset)
{
thisPos.z -= offset;
camerabeforePosZ = cameraTransform.position.z;
}
thisRect.position = thisPos; //캔버스에적용
}
드디어 엔진이 버텨주는 한 지렁이는 끝까지 움직일수 있고, 언제나 맵파일은 깔려있고, 움직이는 느낌 또한 드는 원하던 맵이 완성되었다!!
'Project > Wiggle Quest' 카테고리의 다른 글
[Wiggle Quest - end] 프로젝트 회고 (0) | 2024.10.02 |
---|---|
[Wiggle Quest - 4] 상호작용 UI (0) | 2024.03.11 |
[Wiggle Quest - 3] 아이템 스폰 시스템 (0) | 2024.03.06 |
[Wiggle Quest - 2] 몸집이 늘어나는 지렁이(연결리스트) (0) | 2024.03.06 |