XR플밍 - 9. UnityEngine2D 인터렉티브 프로그래밍 - 개인 프로젝트 3일차(5/30)

이형원·2025년 5월 30일
0

XR플밍

목록 보기
89/215

0.들어가기에 앞서

게임을 만드는 데 있어서 효율성을 고려한 구조도 중요하지만, 일단 굴러가게만이라도 구현하자.

1. 3일차 작업 정리

(왜 자꾸 제일 마지막 작업한 내용이 멋대로 정렬되는지 모르겠다... 최신순으로 정렬되면 좋겠는데 원인을 찾아봐야겠다)

크게 아래와 같이 정리할 수 있겠다

  • 1 스테이지를 튜토리얼 맵으로 설정하여 맵 UI 추가

  • 플레이어와 몬스터의 상호작용 - 데미지 주기를 구현함

  • 플레이어의 죽음 및 몬스터의 죽음을 구현함

  • 게임매니저 구현으로 임시로나마 게임오버를 구현

  • 플레이어의 HP UI를 구현함

  • 오브젝트에 부착하여 효과음을 낼 수 있도록 하는 SFXController 기능 구현


[1스테이지 맵]

2. 문제의 발생과 해결과정

오늘은 버그가 발생한 경우는 적었던 편이다. 기능 개발 위주로 내용을 써 보고자 한다.

2.1 유니티 이벤트의 사용

유니티 이벤트는 애니메이션 중 특정 구간에서 이벤트로 함수를 실행할 수 있는 기능이다.

공격 같은 경우 애니메이션을 Play로 재생하는 방식을 선택했기 때문에 이렇게 구간으로 이벤트를 실행하는 방식이 더 자연스러울 것이다.

또한 이런 애니메이션의 이벤트의 경우 애니메이터가 붙어있는 오브젝트의 함수만 사용할 수 있기 때문에 공격을 하는 함수를 컨트롤러에 추가로 만들었다.

public void Attack()
{
    Collider2D Monster;
    Monster = Physics2D.OverlapCircle(transform.position, 1.5f, m_layerMask);
    if (Monster != null)
    {
        Monster.GetComponent<IDamageable>().TakeDamage(m_playerMeleeAttack);            
    }
}

몬스터와 플레이어 둘 다 애니메이션 이벤트를 적용하여 서로 공격하는 방식을 구현하였다.

2.2 게임매니저의 구현

게임매니저로 플레이어 스킬 쿨타임을 가져왔고, 이를 이용해 쿨타임을 저장하고 게임오버 또한 구현하였다.

2.3 GetComponentInChildren

GetComponentInChildren의 허점이 있다는 사실을 알게 되었다.

이와 같이 HPUI를 구현하기 위해 자식 오브젝트에 있는 Fill 이미지를 가져오려고 했었다.
하지만 HPUI가 제대로 반영되지 않는 상황이 발생하여, 디버깅으로 원인을 살펴보니 자식 오브젝트가 아닌 자신의 이미지를 가져오고 있었다.

왜 이런 것인지 원인을 찾을 수가 없어 검색 등 다양한 방법을 동원했고, 결국 원인은 본인 오브젝트의 물건을 먼저 찾고 자식 오브젝트의 물건을 찾는 것 같다는 결론이 났다.
그래서 다소 억지스러운 방법이지만 부모 오브젝트의 이미지를 제거하고 해당 메소드를 사용했다.
이런 GetComponent 방식을 비선호하는 사람도 있으니 인스펙터로 참조하는 방식도 나쁘지 않을 것이다.

2.4 SFXController

using UnityEngine;

public class Sound
{
    public string Name;
    public AudioClip Clip;
}

public class SFXController : MonoBehaviour
{
    [SerializeField] private Sound[] m_sfx = null;
    private AudioSource m_sfxPlayer;

    private void Awake() => Init();

    private void Init()
    {
        m_sfxPlayer = GetComponent<AudioSource>();
    }

    public void PlaySFX(string p_sfxName)
    {
        m_sfxPlayer.loop = false;
        for (int i = 0; i < m_sfx.Length; i++)
        {
            if (p_sfxName == m_sfx[i].Name)
            {                
                m_sfxPlayer.clip = m_sfx[i].Clip;
                m_sfxPlayer.Play();
                return;
            }
        }
    }
    
    public void LoopSFX(string p_sfxName)
    {
        m_sfxPlayer.loop = true;
        for (int i = 0; i < m_sfx.Length; i++)
        {
            if (p_sfxName == m_sfx[i].Name)
            {
                m_sfxPlayer.clip = m_sfx[i].Clip;
                m_sfxPlayer.Play();
                return;
            }
        }
    }

    public void StopSFX()
    {
        m_sfxPlayer.Stop();
    }
}

이와 같이 기능을 만들어 Loop로 재생해야 하는 효과음은 Loop와 Stop으로 재생하고, 한 번씩만 재생해도 되는 효과음은 Play로 재생하는 방식으로 사용했다.
아무래도 계속 for문을 도는 방식이 비효율적일 수도 있어서 구조의 개선이 필요해 보이지만, 이 방법으로 캐릭터의 걷기, 점프, 검 공격, 게이지 충전과 발사까지의 효과음을 재생할 수 있었다.

3. 수정해야 할 점과 과제

3.1 수정 사항(후순위)

리팩토링과 구조 개선 등이 필요한 코드가 많았다.
다만 우선순위로 둘 작업은 아니며, 시간이 남을 경우에 해당 문제에 대해 고민해보자.
옵저버 패턴에 대해서도 공부를 해 봤지만, 아무래도 다른 것보다 내가 잘 다루지 못하는 취약점이 있었다.

이 부분에 대해서는 공부하고 조언을 얻을 필요가 있을 것 같다.

3.2 (과제) 배경음악을 위한 오디오 매니저, UI매니저 다듬기

현재는 인게임 UI만 구현되어 있으며 타이틀 씬, 일시정지 UI, 게임오버 UI 등 구현해야 할 기능이 많이 남았다.
이 부분에 대해 구현이 필요하다.

3.3 (과제) 스테이지 구현

1스테이지 맵은 얼추 다듬었으니, 본격적으로 게임성을 강조한 스테이지 맵을 만들 필요가 있다.

3.4 (도전) 추가로 구현하고 싶은 것

아무래도 슬슬 아이디어가 떨어져간다는 생각이 들었고, 아래와 같이 구현해야 할 사항을 추가해 보기로 했다.

  • 게이지 충전도에 따라 스펠 공격 데미지 증가 시스템
  • 캐릭터 대쉬 - 다만 공중 대쉬 모션이 없어서 지상에서만 대쉬가 가능하도록 기능을 구현해보고 싶은 시도가 있음
  • 맵의 함정 구현
profile
게임 만들러 코딩 공부중

0개의 댓글