XR 플밍 - 8. UnityEngine3D 입문 - 프로젝트 GwisinRun 2일차 (4/29)

이형원·2025년 4월 29일
0

XR플밍

목록 보기
58/215

0.들어가기에 앞서

1일차에서 구현한 기능은 다양한 것이 있었다.

  • Item에 커서를 갖다대면 UI를 출력하는 기능 구현
  • 양 방향으로 움직이면서 근거리에서만 열 수 있는 문 구현
  • 스위치로 열 수 있는 철창 문의 구현
  • 마우스의 커서를 변경

또한 해결해야 할 과제로 아래와 같은 것들을 고민해야 했다.

  • 아이템 표시 UI를 출력할 때, 어느 정도 가까운 거리에서만 출력하도록 하는 기능 구현
  • 문의 트리거를 이용한 코드를 좀 더 간결하게 만들 방법
  • 인게임 아이템 UI가 트리거와 겹쳤을 때 출력되지 않는 현상 해결

이 외에도 추가로 구현해야 할 기능 및 에셋 서치 등 다양한 활동을 해야 했기 때문에, 오늘은 상대적으로 새로운 기능의 구현보다는 서치와 문제 해결 및 기능 개편 등에 초점을 두었다.

1. 이슈 - 아이템 UI 출력 오류 해결


이슈로 올렸던 해당 문제에 대해서 해결을 해 봐야만 했다. 물론 아이템을 그런 트리거 영역에 두지 않도록 배치하도록 할 수도 있겠지만, 근본적으로 해결할 수 있는 방법이 있다면 한 번 고민해보기로 했다.

우선 이 문제 해결을 위해서 처음 생각해 본 방식은, 레이어를 이용하는 것이었다.
레이어로 스위치나 문 같은 오브젝트를 따로 두고, 아이템을 따로 영역으로 설정하여 만들어서 UI에서 판정하도록 한다면 분리해낼 수 있을 거란 생각에서였다. 하지만 문이나 스위치 등 이런 아이템이 한 두 개가 아닐 건데 이것을 일일히 레이어를 씌우는 건 불편할 거라는 생각이 들었다.

다른 방법은 없을까 고민하면서 유니티 메뉴얼을 참고했다. 그러다 문득, 꽤 유용한 정보를 얻게 되었다.

OnMouseOver()가 무시되는 조건으로 Ignore Raycast라는 레이어로 설정하면 된다는 방법이었다. 이런 레이어가 있었나 확인 차로 유니티 인스펙터에서 확인해보니, 이 레이어가 있었다.

문과 스위치의 트리거 영역을 Ignore Raycast로 설정하고 재생을 시켜보니, 이제는 트리거 영역 안에 있어도 아이템 UI가 출력되는 것을 확인할 수 있었다.

혹시나 트리거 이벤트에 영향이 생겼는지 확인해보았는데, 트리거 영역의 작동에는 이상이 없었다. 여러 방면으로 테스트해 본 결과 기능의 의도대로 변경되었다고 판단하고, 해당 이슈를 해결했다고 판정하여 종료하였다.

2. SwitchController의 기능 개편

이전부터 계속 시도하고 있었지만, 쉽사리 구현되지 않는 기능을 추가해보고자 했다.

내가 필요하다고 생각한 기능은 스위치 하나에 문 여러 개를 조작할 수 있도록 만드는 것이었다.
이를 위해 우선은 지금 만들어 둔 철창 문을 프리팹화 시켜야 했다.

  • 애니메이션이 있는 물체의 경우 유의할 점

애니메이션이 있는 물체의 경우 프리팹으로 만들 경우 유의해야 할 점이 있다. 그건 애니메이션이 있는 셀을 고정시킬 제일 바깥의 Empty Object가 필요하다는 것이다.

단적으로 일어난 문제가 이런 것이다.

  • 애니메이션이 있는 오브젝트를 바깥의 Empty Object로 고정시키지 않았을 경우

이와 같은 문제가 발생하는 것은 아무래도 애니메이션 자체가 특정 위치의 오브젝트를 목적 위치의 오브젝트로 이동시키는 과정으로 판정하기 때문이다. 즉, x, y, z 좌표를 모두 가지고 있기 때문에 해당 위치로 물체를 이동시키는 애니메이션을 출력하기 위해서 이와 같은 의도치 않은 상황이 발생할 수 있는 것이다.

이런 유의점을 기억해 두면서, SwitchController의 기능을 개편해보자.

스위치 하나로 여러 개의 문을 열고 닫게 하기 위해서, 우선은 가장 쉬운 방법으로 애니메이터를 받는 [SerializeField] 두 개를 받고, 프리팹 두 개를 각각의 인스펙터 창에 참조시켜 보았다.
이와 같은 방법으로 테스트해 보았을 때, 정상 작동하는 것을 확인했다. 하지만, 이렇게 필요할 때마다 스크립트에서 수정하는 방식은 그리 바람직하지 않다고 생각했다.

무언가 방법이 없을까 고민하다가, 문득 리스트를 활용한 방법으로 구현 가능하지 않을까 생각해 아래와 같이 코드 내용을 변경하였다.

using System.Collections.Generic;
using UnityEngine;

public class SwitchController : MonoBehaviour, IInteractable
{
    [SerializeField] List<Animator> m_objectAnimator;
    private bool m_switchOn = false;
    private bool m_interactable = false;

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.tag == "Player")
            m_interactable = true;
    }
    private void OnTriggerExit(Collider other)
    {
        if (other.gameObject.tag == "Player")
            m_interactable = false;
    }

    public void Interact()
    {
        if (m_interactable)
        {
            m_switchOn = !m_switchOn;
            for (int i = 0; i < m_objectAnimator.Count; i++)
            {
                boolAnimator(m_objectAnimator[i]);
            }
        }
    }

    // 현 단계에선 번갈아가면서 bool값이 번갈아가게 되어 있으나,
    // bool 변수 세부 값을 조정할 수 있도록 세팅할 건지도 고민중
    private void boolAnimator(Animator animator)
    {
        m_switchOn = !m_switchOn;
        animator.SetBool("IsOpen", m_switchOn);
    }
}

우선 지금 당장의 의도는, 한쪽 문이 열리면 다른 쪽 문이 닫히는 구조를 생각하고 이와 같이 코드를 작성하였다.


리스트를 사용한 방식으로 애니메이터를 보다 쉽게 관리할 수 있었다. 한 개만 사용해도 되고 두 개 이상을 사용해도 된다. 또한 해당 코드의 결과는 아래와 같이 출력된다.

이와 같은 기능을 추가했다고 팀장님께 말씀드렸고, 해당 기능을 잘 이용하면 왔던 길을 돌아가지 못하게 막는 용도로나, 다양한 용도로 쓸 수 있겠다는 피드백을 받았다. 또한 bool값을 상세 설정할지에 대한 여부는 이후 게임을 만들어보는 과정에서 결정하기로 했다.

3. ItemInfoUIController 기능 개편

이전에 만들었던 ItemInfoUIController에 관해서 팀장님이 피드백한 내용이 있었다.

지금 단계에서 당장 필요할 지는 모르겠지만, 아이템과의 거리가 너무 먼 상태에서도 아이템 UI가 표시되면 기능적으로 부자연스러울 수 있다.

해당 기능을 개편하기 위해선 아무래도 나머지 팀원과의 결과물을 합친 다음에 게임 시연을 해 보고 나서 해야 한다고 생각했으나, 문득 생각해보니 혼자서 작업할 수 있는 부분이라고 생각했다.
닷지로 프로젝트를 만들었을 당시, 플레이어를 겨누는 터렛을 만들기 위해 사용했던 방법을 써 먹으면 될 것 같았다. 따라서 아래와 같이 코드 내에서 조건을 추가했다.

using UnityEngine;

public class ItemInfoUIController : MonoBehaviour
{
    [SerializeField] Canvas m_canvas;
    [SerializeField] GameObject m_panel;
    private RectTransform m_panelpos;
    [SerializeField] private float m_detectRadius;
    [SerializeField] private LayerMask m_playerLayer;

    public void Awake()
    {
        m_panelpos = m_panel.GetComponent<RectTransform>();
    }


    private void OnMouseOver()
    {
    	// 추가한 조건
        if (Physics.OverlapSphere(transform.position, m_detectRadius, m_playerLayer).Length > 0)
        {
            m_panel.SetActive(true);

            Vector2 localPos = Vector2.zero;

            RectTransform rectTransform = m_canvas.transform as RectTransform;
            Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);

            RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, mousePos, m_canvas.worldCamera, out localPos);
            m_panelpos.anchoredPosition = localPos;
        }
        else
        {
            m_panel.SetActive(false);
        }
    }

    private void OnMouseExit()
    {
        m_panel.SetActive(false);
    }
}

아이템의 반경 몇 m 내에 플레이어가 인지되었을 경우에만 UI가 뜨도록 조건을 추가했다. 또한 거리가 멀어지면 바로 UI가 꺼지도록 else 조건도 추가했다. 이를 테스트하면 아래와 같이 나온다.

우리가 앞으로 만들 게임은 1인칭 시점으로 진행할 예정이니, 이와 같이 플레이어와의 거리를 설정해 놓고 아이템의 UI가 출력되는 방식이 자연스러울 것이다.

4. 오류 - invalid texture used for cursor


사실 어제자 마우스 커서를 변경한 뒤부터 계속 발생하는 경고가 있었다.
해당 경고의 내용을 보면 커서에 쓰인 이미지가 유효하지 않은 텍스쳐를 쓰고 있다고 오류를 주는 모습으로 보이는데, 일단 작동 자체는 정상적으로 되니 이 오류 자체를 그다지 신경 쓰고 있지 않고 있었다.

하지만 팀장님이 Build해서 테스트를 진행하고 있던 와중에 커서에서 자꾸 오류가 발생한다고 나에게 문의를 해왔다.
나는 해당 문제를 해결해보려고 서치를 시작했다.

문제의 원인 자체는 간단하다. 내가 이전에 커서 작업을 했을 때 처음에는 2D 스프라이트로 작업을 했었는데, 중간에 커서 변경 방법을 알게 되어 해당 이미지를 그대로 반영한 게 문제였다.

커서는 커서 전용 Texture Type이 따로 있고 이것이 커서로 설정되어 있지 않아 발생한 오류였다. 해당 스프라이트로 수정한 후 빌드까지 해 보고서 오류가 사라지고 빌드 단계에서도 문제가 없는 것을 확인하였다.

5. 게임에 사용할 에셋 선별

오늘은 결과적으로 기능에 대한 추가보단 기존 기능을 개편하고 에셋을 찾아 정리하는 것 위주로 작업을 하였다. 팀장님의 요청으로 HP와 스태미너 에셋이 결정된 후에 해당 스크립트 작업을 하라 하셨고, 맵 내의 이벤트 시스템 또한 맵이 어느 정도 구현이 되어야 진행할 수 있는 부분이라 당장 작업할 수 있는 부분이 많지는 않았다.

그래서 학원에서 제공하는 에셋을 선별하고 어울리는 에셋을 찾는 것 위주로 우선 작업을 진행하고, 사용할 수 있을 것으로 보이는 에셋 목록을 팀 디스코드 채팅에 게제하였다. 팀 내의 작업이 어느 정도 완료가 된 후부터 UI작업을 마저 하고 이벤트에 대한 작업을 할 예정이다.

6. 첫 충돌 발생

오늘자 작업을 마무리한 후 Pull Request를 하려는데 아래와 같이 merge 불가가 떴다.

1일차부터 지금까지 충돌이 없었지만 첫 충돌이 발생한 것이다. 어제자만 해도 다른 팀원의 설정 변경으로 내 테스트 씬이 약간 변경되거나 하는 문제가 있기는 했는데 충돌이 발생할 거라고는 생각지도 못했다. 중간중간 Pull이 있었던 터라 꾸준히 했었는데 뭐가 문제가 있는지 확인해보았다.

정말 다행히도 충돌의 원인이 뭔지 바로 알 수 있었다. 충돌이 발생한 파일은 Build Setting에서 발생했는데, 해당 파일이라고 한다면 마우스 커서 오류 문제를 테스트해 본다고 Build Setting에 내 테스트 씬을 넣은 것이 충돌한 것이다.

빌드 세팅에서 내 씬을 삭제한 후 다시 PR을 살펴보니 충돌이 사라졌다고 뜨는 것을 확인했다.

이번 경우에는 다소 사소한 충돌이기는 했지만, 이런 방식으로도 충돌이 발생할 수 있다는 점에서 유의해야 하는 것임은 확실하게 느꼈다.

profile
게임 만들러 코딩 공부중

0개의 댓글