Unity - Only Up 모방 프로젝트

한예준·2025년 5월 21일

오늘은 어제에 이어 개인 프로젝트 진행 내용을 공유하고자 한다. 어제 인벤토리 UI를 만드는 것으로 작업을 마쳤는데, 인벤토리 UI를 수정하고, 상호작용 시스템을 완성하는 것으로 오늘 프로젝트를 시작하겠다.


인벤토리 UI 수정

기존 인벤토리 시스템


기존 인벤토리 UI는 Tab키를 눌렀을 때 이런 식으로 띄워지고, 인벤토리 UI 내의 슬롯을 선택하여 아이템을 사용하는 식으로 구현했다. 하지만, Only Up 같은 게임에서 매번 Tab키를 눌러 아이템을 사용하는 것은 상당히 불친절한 방식이라고 생각이 들어 인벤토리 시스템을 수정하기로 했다.

인벤토리 시스템 수정 계획

  • 화면 하단에 퀵슬롯을 만들어 아이템을 배치한다.
    • 아이템을 얻으면 왼쪽슬롯부터 아이템이 배치된다.
    • 키보드 상단 숫자를 눌러 해당 슬롯에 있는 아이템을 선택한다.
    • 선택한 아이템을 F키를 눌러 사용한다.

점프대 기능 구현

  • 플레이어가 위로 올라갈 시 강한 힘으로 점프를 시켜주는 점프대 오브젝트를 만들어보겠다.
    • JumpPad 오브젝트를 만들고, 밑에 Cube 오브젝트를 두개 만들어준다.
    • Cube 오브젝트 하나는 작게 만들고 위로 튀어나오게, 하나는 약간 크게 만들어서 주변을 감싸주는 형태로 만든다. (위가 아닌 다른 면에 닿을 시에 기능이 발동되는 것을 막기 위함.)
    • 이후 JumpPad 스크립트를 만들어서 위로 튀어나온 큐브 오브젝트에 붙여준다.
    • 정상적으로 작동하는 것을 확인한 후 프리팹화 시킨다.

플랫폼 구현

테스트용 플랫폼 생성

  • Box Collider가 붙은 Cube 오브젝트를 생성하고 크기를 조정하여 테스트용 플랫폼을 구현하였다.
    • 위치를 적당히 조정하여 플레이어가 점프를 통해 이동할 수 있도록 하였다.
    • 테스트 도중 플레이어가 점프한 상태로 벽에 붙으면 움직이지 않거나 벽에 붙은 채로 점프가 불가능한 문제가 발생함을 알 수 있었다.
  • 구글링 결과, Physic Material을 통해 마찰력을 조정해줘야 한다는 사실을 알았다.
    • 만들어 놓은 Cube Object의 Box Collider의 인스펙터 창의 Material 항목에 Dynamic Friction, Static Friction을 0으로 조정한 Platfrom Friction(Physic Material)을 넣어주었다.
    • 그 결과, 플레이어가 벽에 붙는 문제가 해결되었음을 확인했다.

움직이는 플랫폼 구현

  • Cube 프리팹의 크기를 조정하여 MovingPlatform 오브젝트를 생성하였다.
    • MovingPlatform.cs스크립트를 작성하여 위치를 이동할 수 있도록 했다.
      • waypoints 에 위치를 표시하는 빈 오브젝트를 넣어 플랫폼이 이동해야 할 경로를 지정하였다.
      • curWayPointIndex 변수로 현재 플랫폼이 향하고 있는 waypoint를 지정한다.
      • 코루틴을 이용하여 waitTime 변수만큼 대기하고 다음 waypoint로 이동하는 것을 반복하도록 구현하였다.
    • 한가지 사소한 문제가 발생했는데, waypoint 오브젝트를 MovingPlatform 오브젝트의 자식 오브젝트로 두어서 MovingPlatform이 이동함에 따라 waypoint도 같이 이동하여 무한히 한 방향으로 이동하는 문제가 발생하여 오브젝트를 분리하는 것으로 해결하였다.
  • 실제 플레이 해보니 또 다른 문제가 발생하였는데, 플레이어가 MovingPlatform 오브젝트 위로 올라갔을 때, 플레이어가 오브젝트를 따라 움직이지 않고 따로 움직인 것이다.
    • 처음엔 MovingPlatformFriction 마찰력 값을 올리면 플랫폼의 이동에 따라 플레이어도 움직일 수 있을 거라 생각했지만, 이를 통해 해결되지 않았다.
    • 해결방법을 고민하던 중 위에 발생했던 문제를 역으로 이용하여 해결할 수 있을 거라 생각했다. 바로 플레이어가 플랫폼의 위에 올라와 있을 때 플레이어 오브젝트를 MovingPlatform의 자식 오브젝트로 두고, 플랫폼에서 떠났을 때 이를 해제하는 것이었다.
    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.CompareTag("Player"))
        {
            player = collision.transform;
            player.SetParent(transform); 
        }
    }

    private void OnCollisionExit(Collision collision)
    {
        if (collision.gameObject.CompareTag("Player"))
        {
            player.SetParent(null); 
            player = null;
        }
    }
  • 이 때, 플레이어가 MovingPlatform 오브젝트의 옆에서 닿을 때도 오브젝트를 따라 움직이는 현상이 발생했다. 따라서
        if (collision.gameObject.CompareTag("Player") && collision.transform.position.y > transform.position.y)

충돌이 오브젝트의 위에서 일어났을 때만 아래 기능을 실행할 수 있도록 수정하였다.

  • 실행 결과 의도한대로 실행되고 있음을 확인할 수 있었다.

레이저 트랩 플랫폼 구현

레이저를 발사해서 플레이어가 레이저에 닿으면 위에서 함정이 떨어지는 플랫폼을 구현해보려고 한다.

  • 빈 오브젝트인 LaserPlatform 오브젝트를 만들고 하위 오브젝트로 플레이어가 올라갈 수 있는 BasePlatform을 만들었다.
  • 또, 레이저를 발사하는 LaserShootPlatform과 레이저가 도달하는 LaserShootPlatform2를 만들고, 위에 Rigidbody가 달려있는 Trap 오브젝트를 만든다.
    • Trap은 키네마틱 상태이고, 레이저가 플레이어에게 닿는 순간 Trap의 키네마틱이 false가 되게 만들었다.

3인칭 카메라 전환

  • Q키를 눌렀을 때 카메라를 3인칭 카메라로 전환하고 다시 Q키를 누르면 메인카메라로 전환하는 로직을 구현해보고자 한다.
//CameraSwitch.cs
public class CameraSwitch : MonoBehaviour
{
    public Camera mainCamera;
    public Camera thirdPersonCamera;

    private bool isThirdPerson = false;

    private void Awake()
    {
        if (mainCamera == null)
        {
            mainCamera = Camera.main;
        }
        if (thirdPersonCamera == null)
        {
            thirdPersonCamera = GetComponent<Camera>();
        }
        
        mainCamera.enabled = true;
        thirdPersonCamera.enabled = false;
    }

    public void OnSwitchCameraInput(InputAction.CallbackContext context)
    {
        if (context.phase == InputActionPhase.Started)
        {
            isThirdPerson = !isThirdPerson;
            
            mainCamera.gameObject.SetActive(!isThirdPerson);
            mainCamera.enabled = !isThirdPerson;
            thirdPersonCamera.gameObject.SetActive(isThirdPerson);
            thirdPersonCamera.enabled = isThirdPerson;
        }
    }
}
  • 이 스크립트를 CameraContainer에 붙이고, 연결 후 실행해보니 의도한대로 실행되고 있음을 확인할 수 있었다.

0개의 댓글