프로젝트/건즈앤 레이첼스
[유니티 프로젝트] 랜덤 생성맵 포탈 구현 (맵간의 이동) 및 미니맵 포지션 구현
Bueong_E
2023. 3. 19. 20:18
반응형
SMALL
현재 추가 구현 사항은 아래와 같다.
- 플레이어와 포탈 접촉시 포탈이 향하는 다음 방으로 플레이어 이동( 해당 맵을 부모 오브젝트로 변경 및 맞는 포지션의 포탈로 이동)
- 미니맵 포지션캐릭터 위치에 따라 이동 및 위치에 맞는 미니맵 UI 에 깜빡이며 표시 (동영상 핑크 색 부분 참고)
추가로 구현해야할 사항은 아래와 같다.
- 시작시 스타트룸을 제외한 모든 룸들 ActiveSelf = false 로
- 플레이어가 다음 방에 갈시 해당 룸을 ActiveSelf = true로
**문제점으로는 약간의 끊김이 발생하는데 코드가 문제인지 아니면 컴퓨터의 문제인지 확인이 애매하다
아마 임시로 만든 맵 제너레이터에 붙인 코드여서 그럴수도 있겠다 라는 생각이 드는데 일단 코드 최적화를 해보고 문제가 생기는지 확인해야겠다.
여기서 핑크색 부분 (플레이어가 있는 부분) 의 경우 추가적인 레이어를 제작하여 플레이어의 방 이동시 해당 방의 위치로 변경되게 하였고 코루틴을 이용하여 깜빡이게 만들었다.
코드
UI Director 코드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
using UnityEngine.Tilemaps;
public class UIMapGenDirector : MonoBehaviour
{
public MapGenerator MapGenerator;
public DungeonSceneMain main;
public Button btnMapReGen;
public TMP_Text txtMapCount;
public Button btnHiddenRoom;
public Text txtHiddenRoom;
public Button btnMaxRowPlus;
public Button btnMaxRowMinus;
public Button btnMaxColPlus;
public Button btnMaxColMinus;
public TMP_Text txtRowCol;
public Camera mainCamera;
public Camera miniMapCam;
private float defaultFOV = 60f; // 기본 FOV 값
public Vector3 currentPlayerMapPos;
public GameObject imgCurrentMap;
public void Init()
{
this.imgCurrentMap = Instantiate(this.imgCurrentMap);
this.StartCoroutine(this.mapFlickerling());
this.txtRowCol.text = string.Format("MaxRow : {0}\nMaxCol : {1} ", this.MapGenerator.maxRow, this.MapGenerator.maxCol);
this.AdjustFOV();
this.btnMapReGen.onClick.AddListener(() =>
{
var maps = GameObject.FindGameObjectsWithTag("UsingRoom");
for (int i = 0; i < maps.Length; i++) { Destroy(maps[i]); }
this.MapGenerator.mapCount = 0;
this.MapGenerator.Init();
this.AdjustFOV();
this.main.spawnPlayer();
});
this.btnHiddenRoom.onClick.AddListener(() =>
{
this.MapGenerator.isHiddenRoom = !this.MapGenerator.isHiddenRoom;
if (this.MapGenerator.isHiddenRoom) this.txtHiddenRoom.text = "Hidden Room ON";
else this.txtHiddenRoom.text = "Hidden Room OFF";
});
this.btnMaxRowPlus.onClick.AddListener(() =>
{
this.MapGenerator.maxRow++;
this.txtRowCol.text = string.Format("MaxRow : {0}\nMaxCol : {1} ", this.MapGenerator.maxRow, this.MapGenerator.maxCol);
});
this.btnMaxRowMinus.onClick.AddListener(() =>
{
this.MapGenerator.maxRow--;
this.txtRowCol.text = string.Format("MaxRow : {0}\nMaxCol : {1} ", this.MapGenerator.maxRow, this.MapGenerator.maxCol);
});
this.btnMaxColPlus.onClick.AddListener(() =>
{
this.MapGenerator.maxCol++;
this.txtRowCol.text = string.Format("MaxRow : {0}\nMaxCol : {1} ", this.MapGenerator.maxRow, this.MapGenerator.maxCol);
});
this.btnMaxColMinus.onClick.AddListener(() =>
{
this.MapGenerator.maxCol--;
this.txtRowCol.text = string.Format("MaxRow : {0}\nMaxCol : {1} ", this.MapGenerator.maxRow, this.MapGenerator.maxCol);
});
}
private void LateUpdate()
{
var playerPos = main.player.transform.position;
this.miniMapCam.transform.position = new Vector3 (playerPos.x, playerPos.y,-500);
this.imgCurrentMap.transform.position = new Vector3(this.currentPlayerMapPos.x+7, this.currentPlayerMapPos.y+10, -22);
this.mainCamera.transform.position = new Vector3(playerPos.x, playerPos.y, -10);
}
private IEnumerator mapFlickerling()
{
while (true)
{
this.imgCurrentMap.SetActive (false);
yield return new WaitForSeconds(1f);
this.imgCurrentMap.SetActive(true);
yield return new WaitForSeconds(1f);
}
}
private void AdjustFOV()
{
//float mapSize = Mathf.Max(this.MapGenerator.maxCol, this.MapGenerator.maxRow) * 32f; // 타일맵 전체 크기 계산
//float distance = mapSize / (2f * Mathf.Tan(defaultFOV * 0.5f * Mathf.Deg2Rad)); // 카메라와 타일맵 사이의 거리 계산
//float requiredFOV = 2f * Mathf.Atan(mapSize / (2f * distance)) * Mathf.Rad2Deg; // 필요한 FOV 값 계산
//this.mainCamera.fieldOfView = requiredFOV; // FOV 값을 조정하여 메인 카메라에 적용
}
}
Dungeon Scene Main 코드
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DungeonSceneMain : MonoBehaviour
{
[SerializeField]
private UIMapGenDirector UIdirector;
[SerializeField]
private MapGenerator generator;
[SerializeField]
public GameObject player;
public Action<Vector2, string> getPortalInfo;
public Action spawnPlayer;
void Awake()
{
this.generator.sendMapCount = (mapCount) =>
{
this.UIdirector.txtMapCount.text = string.Format("Map Count : {0}", mapCount);
};
this.generator.Init();
this.UIdirector.Init();
this.spawnPlayer = () =>
{
var startRoom = this.generator.wholeRoomList.Find(x => x.transform.name.Contains("Start"));
this.player = Instantiate(this.player, startRoom.transform);
this.player.transform.localPosition = Vector2.zero;
this.UIdirector.currentPlayerMapPos = startRoom.transform.position;
};
this.spawnPlayer();
this.getPortalInfo = (x, y) =>
{
if (y.Contains("0"))
{
//Destroy(GameObject.FindGameObjectWithTag("Player"));
int objIndex = this.generator.wholeRoomList.FindIndex(obj => (Vector2)obj.transform.position == new Vector2(x.x,x.y+this.generator.mapDist));
//var go = Instantiate(this.player, this.generator.wholeRoomList[objIndex].transform);
var spawnPos = this.generator.wholeRoomList[objIndex].transform.GetChild(2).position;
this.player.transform.parent = this.generator.wholeRoomList[objIndex].transform;
this.player.transform.position = new Vector2(spawnPos.x, spawnPos.y+2);
this.UIdirector.currentPlayerMapPos = this.generator.wholeRoomList[objIndex].transform.position;
}
else if(y.Contains("1"))
{
//Destroy(GameObject.FindGameObjectWithTag("Player"));
int objIndex = this.generator.wholeRoomList.FindIndex(obj => (Vector2)obj.transform.position == new Vector2(x.x + this.generator.mapDist, x.y ));
//var go = Instantiate(this.player, this.generator.wholeRoomList[objIndex].transform);
var spawnPos = this.generator.wholeRoomList[objIndex].transform.GetChild(3).position;
this.player.transform.parent = this.generator.wholeRoomList[objIndex].transform;
this.player.transform.position = new Vector2(spawnPos.x+1, spawnPos.y);
this.UIdirector.currentPlayerMapPos = this.generator.wholeRoomList[objIndex].transform.position;
}
else if (y.Contains("2"))
{
//Destroy(GameObject.FindGameObjectWithTag("Player"));
int objIndex = this.generator.wholeRoomList.FindIndex(obj => (Vector2)obj.transform.position == new Vector2(x.x , x.y - this.generator.mapDist));
//var go = Instantiate(this.player, this.generator.wholeRoomList[objIndex].transform);
var spawnPos = this.generator.wholeRoomList[objIndex].transform.GetChild(0).position;
this.player.transform.parent = this.generator.wholeRoomList[objIndex].transform;
this.player.transform.position = new Vector2(spawnPos.x, spawnPos.y-1);
this.UIdirector.currentPlayerMapPos = this.generator.wholeRoomList[objIndex].transform.position;
}
else if (y.Contains("3"))
{
//Destroy(GameObject.FindGameObjectWithTag("Player"));
int objIndex = this.generator.wholeRoomList.FindIndex(obj => (Vector2)obj.transform.position == new Vector2(x.x - this.generator.mapDist, x.y));
//var go = Instantiate(this.player, this.generator.wholeRoomList[objIndex].transform);
var spawnPos = this.generator.wholeRoomList[objIndex].transform.GetChild(1).position;
this.player.transform.parent = this.generator.wholeRoomList[objIndex].transform;
this.player.transform.position = new Vector2(spawnPos.x - 1, spawnPos.y);
this.UIdirector.currentPlayerMapPos = this.generator.wholeRoomList[objIndex].transform.position;
}
};
}
}
portalController 코드
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PortalController : MonoBehaviour
{
[SerializeField]
private DungeonSceneMain main;
private void Awake()
{
this.main = GameObject.Find("DungeonSceneMain").GetComponent<DungeonSceneMain>();
}
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.gameObject.tag == "Player")
{
Debug.Log("플레이어 닿음");
var parentPos = this.transform.parent.parent.position;
var protalName = this.transform.parent.name;
this.main.getPortalInfo(parentPos, protalName);
}
}
}
반응형
LIST