[Unity] 3D 탑다운 무한 맵Unity/Portfolio2024. 11. 9. 23:22
Table of Contents
📹영상
영상에서 움직이고있는 트랜스폼 핸들이 플레이어 입니다.
플레이어의 이동에 맞춰 카메라에 빈 월드가 보이지 않게 블레이어 주변 9개의 맵을 재배치 합니다.
📌코드
InGameMapController.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.AddressableAssets;
using Cysharp.Threading.Tasks;
public class InGameMapController : MonoBehaviour
{
[SerializeField]
private AssetReferenceGameObject planePrefab;
[SerializeField]
private List<MapPlane> mapPlanes = new List<MapPlane>();
[SerializeField]
private Vector2 planeSize = new Vector2(65f, 47.5f);
private Vector2 playerCoords = Vector2.zero;
private void Start()
{
// 플레이어 주변 9개 맵 생성
RepositionMap();
}
private void Update()
{
CheckPlayerCoords();
}
private void CheckPlayerCoords()
{
// 현재 플레이어의 좌표
// (0, 0)가운데, (-1, 1)왼쪽 위, (1, -1)오른쪽 아래
Vector2 coord = playerCoords;
// 다른 plane으로 넘어가는 경계선 좌표
// (0, 0)일땐 곱하면 0되버리니까 더하기or빼기로 보정
var xMin = (coord.x * planeSize.x) - (planeSize.x / 2f);
var xMax = (coord.x * planeSize.x) + (planeSize.x / 2f);
var zMin = (coord.y * planeSize.y) - (planeSize.y / 2f);
var zMax = (coord.y * planeSize.y) + (planeSize.y / 2f);
Vector3 playerPos = InGameManager.Instance.Player.transform.position;
// 플레이어가 다른 plane으로 넘어갔는지 체크
// 넘어갔다면 플레어의 새 좌표를 만듦
if (playerPos.x < xMin)
coord.x -= 1;
else if(playerPos.x > xMax)
coord.x += 1;
if(playerPos.z < zMin)
coord.y -= 1;
else if(playerPos.z > zMax)
coord.y += 1;
// 플레이어가 다른 plane으로 넘어갔다면 맵을 재배치
if (playerCoords != coord)
{
playerCoords = coord;
RepositionMap();
}
}
private async UniTaskVoid RepositionMap()
{
// 플레이어 주위 좌표(인덱스는 중요하지 않음)
// 0, 1, 2
// 3, 4, 5
// 6, 7, 8
List<Vector2> around = new List<Vector2>()
{
Vector2.left + Vector2.up + playerCoords,
Vector2.up + playerCoords,
Vector2.right + Vector2.up + playerCoords,
Vector2.left + playerCoords,
Vector2.zero + playerCoords,
Vector2.right + playerCoords,
Vector2.left + Vector2.down + playerCoords,
Vector2.down + playerCoords,
Vector2.right + Vector2.down + playerCoords
};
// 플레이어 주위 9개 좌표에 없는(너무 멀어진) 맵들
List<MapPlane> repositionList = mapPlanes.Where(t => !around.Contains(t.coords)).ToList();
// 새로 들어온 플레이어 주변 좌표들
// 기존 좌표의 땅이 아직도 주변 좌표라면 그대로 두면 되니까 차집합으로 새 좌표만 구함
List<Vector2> newCoords = around.Except(mapPlanes.Select(x => x.coords)).ToList();
for (int i = 0; i < newCoords.Count; i++)
{
Vector2 coord = newCoords[i];
// 피봇이 plane모델의 센터니까 크기만큼 곱해서 위치를 구함
Vector3 pos = new Vector3(coord.x * planeSize.x, -1.25f, coord.y * planeSize.y);
// 너무 멀어진 맵들을 새로운 주변 위치로 재배치
if (repositionList.Count > i)
{
repositionList[i].coords = coord;
repositionList[i].transform.position = pos;
}
// Start에서 호출돼서 아직 plane오브젝트들이 없다면 어드레서블 프리팹으로 생성
else
{
var newPlane = await StaticManager.Instance.ResourceManager.InstantiateAsset<MapPlane>(planePrefab);
newPlane.coords = coord;
newPlane.transform.position = pos;
newPlane.transform.parent = transform;
mapPlanes.Add(newPlane);
}
}
}
}
MapPlane.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MapPlane : MonoBehaviour
{
public Vector2 coords;
}
📌인스펙터
`Plane Prefab` : 맵 오브젝트 프리팹입니다 `AssetReferenceGameObject`타입으로 어드레서블로 불러와 사용했습니다
`Map Planes` : 생성된 맵들의 리스트입니다 미리 채워져있어도, 비어있어도 작동하도록 돼있습니다
`Plane Size` : 맵 오브젝트의 3D 모델 사이즈 입니다 수동으로 입력합니다
'Unity > Portfolio' 카테고리의 다른 글
[Unity] 3D로 구현해본 승리의 여신 니케 (4) | 2024.10.28 |
---|---|
[Unity] 페르소나 5 메뉴 UI 구현 (1) | 2024.10.06 |
대구 게임 아카데미 프로젝트 3종 (0) | 2024.06.22 |
[Unity] 퍼즐게임 레벨에디터 구현 (0) | 2022.07.30 |