Coding Feature.

[Unity 2D] Portal 같은 게임 만들기 #2 포탈 매커니즘 구현하기 1(위치 변환) 본문

Toy Project/mini-portal [Unity2D]

[Unity 2D] Portal 같은 게임 만들기 #2 포탈 매커니즘 구현하기 1(위치 변환)

codingfeature 2024. 1. 5. 16:20

이제 본격적으로 Portal 게임의 핵심인 포탈과 관련된 매커니즘을 구현해보도록 하겠습니다!

 

먼저 포탈 매커니즘은 아래 그림 하나로 요약됩니다!

출처 - 위키피디아

 

한 포탈로 들어가면 다른 포탈로 나옵니다.

나올 때 들어갈때의 속도와 방향과 같게 나갑니다.

 

위 매커니즘을 구현하기 위해 우선 오렌지색 포탈과 파랑색 포탈 Sprite을 가져옵니다.

 

 

각각 OrangePortal, BluePortal이라고 이름지었습니다!

 

추후에 Collision Detection하기 위해 Box Collider 2D 컴포넌트를 각각 부여하였습니다.

그리고 포탈의 물리적 특성(플레이어와 부딪힐 경우 막히는 것 등)을 없애기 위해 Is Trigger 부분을 체크합니다.

 

 

 

우선 포탈과 관련된 매커니즘을 따로 관리하기 위해 Portal Script를 짜도록 하겠습니다.

Portal Script라는 empty한 오브젝트를 만들고 PortalScript.cs 파일을 만들고 집어넣었습니다.

 

우선 포탈 매커니즘 중 위치 변환을 구현하기 위해 다음과 같이 코드를 작성해보았습니다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PortalScript : MonoBehaviour
{
    public GameObject player;
    public GameObject orangePortal;
    public GameObject bluePortal;

    Vector3 playerEnterVelocity; // 플레이어가 포탈에 들어갈 때의 속도.

    bool m_EnteredPortal; // 플레이어가 포탈에 들어간 경우를 확인하는 Boolean.
    bool isTouchingOrange, isTouchingBlue; // 플레이어가 포탈에 닿은 경우를 확인하는 Boolean.

    // Start is called before the first frame update
    void Start()
    {
        m_EnteredPortal = false;
    }

    // Update is called once per frame
    void Update()
    {
        playerEnterVelocity = player.GetComponent<Rigidbody2D>().velocity;

        // 플레이어가 포탈에 닿았는가 확인.
        isTouchingOrange = Physics2D.IsTouching(player.GetComponent<BoxCollider2D>(), orangePortal.GetComponent<BoxCollider2D>());
        isTouchingBlue = Physics2D.IsTouching(player.GetComponent<BoxCollider2D>(), bluePortal.GetComponent<BoxCollider2D>());

        if (isTouchingOrange && !m_EnteredPortal) // 오렌지 포탈에 닿은 경우 + 이미 들어간 적이 없는 경우.
        {
            m_EnteredPortal = true;
            player.transform.position = bluePortal.transform.position; //  오렌지 포탈로 위치 변환.
        }

        if (isTouchingBlue && !m_EnteredPortal) // 블루 포탈에 닿은 경우 + 이미 들어간 적이 없는 경우.
        {
            m_EnteredPortal = true;
            player.transform.position = orangePortal.transform.position; //  블루 포탈로 위치 변환.
        }

        if (!isTouchingBlue && !isTouchingOrange)
        {
            m_EnteredPortal = false;
        }
    }
}

 

플레이어, 두 개의 포탈 Game Object를 우선 Unity에서 끌고와서 집어넣었습니다.

 

위 코드를 통해 사용자가 Orange 또는 Blue 포탈에 닿았을 때 반대편 포탈로 위치가 바뀌도록 할 수 있습니다.

 

그리고 m_EnteredPortal 불리언 변수를 통해, 다른 포탈로 이동 후 다시 이동된 포탈의 Collsion이 트리거되어 원래 포탈로 이동되는 버그를 방지하였습니다.

 

사실 위 코드는 완벽하지 않습니다.

사용자가 포탈의 어느 위치에 닿아도 반대 포탈의 위치 정중앙에 스폰이 되기 때문입니다.

이 부분은 포탈의 크기가 커지면 문제가 발생할 것입니다. 

다만 현재는 작은 포탈로 시험하고 있으니 일단 넘어가고 추후에 개선해보기로 하겠습니다!

 

 

 

 

위와 같은 스테이지 구현 시 잘 되는 것 같아 보이지만 아래와 같이 만들면 어떨까요?

 

 

이상하죠.. ㅎㅎ

 

위치는 변환되지만 사용자가 포탈에 들어갈 때의 방향과 같게끔 다른 포탈에서 나와야 하지만 이 내용은 구현하지 않았기 때문에 발생하는 문제입니다.

 

이 내용은 다음에 구현해보도록 하겠습니다!