프로젝트/건즈앤 레이첼스

[유니티 프로젝트] 랜덤 생성맵 포탈 구현 (맵간의 이동) 및 미니맵 포지션 구현

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