[TIL] Unity - 2D 탑다운 게임 트러블 슈팅

MINO·2024년 6월 13일
0
post-thumbnail

2024-06-13


트러블 슈팅 (1)

상황

플레이어가 아이템을 먹고난 뒤, 적의 공격이 무효화되는 버그가 발생하였다.

버그 O버그 X

분석

버그가 발생한 플레이 화면은 초록 포션 으로, 최대 체력을 증가시키는 효과이고,
버그가 발생하지 않은 플레이 화면은 파란 포션 으로, 투사체 개수를 증가시키는 효과이다.
또, 버그가 발생한 포션은 빨간 포션 으로, 현재 체력을 증가시키는 효과이다.

근접 몬스터원거리 몬스터로도 비교해보았지만, 몬스터의 종류는 버그와 상관이 없었다.


시도 (1)

포션을 먹고 난 뒤, 투사체나 플레이어의 Layer 에 문제가 생긴 것이 아닌지 확인해보았다.

각각 오브젝트의 설정된 Layer 를 확인해보기도 하고,
Project Settings - Physics 2D - Layer Collision Matrix 도 확인해봤지만
문제가 없었다.


시도 (2)

아이템을 관리하는 스크립트와 오브젝트와 잘 연결됐는지 확인도 해봤지만, 해결할 수 없었다.

public abstract class PickupItem : MonoBehaviour
{
    [SerializeField] private AudioClip pickupSound;

    private void OnTriggerEnter2D(Collider2D collision)
    {
        OnPickedUp(collision.gameObject);

        if (pickupSound != null)
            SoundManager.PlayClip(pickupSound);

        Destroy(gameObject);
    }

    protected abstract void OnPickedUp(GameObject gameObject);
}


public class PickupHeal : PickupItem
{
    [SerializeField] private int healValue = 10;

    protected override void OnPickedUp(GameObject go)
    {
        HealthSystem healthSystem = go.GetComponent <HealthSystem> ();
        healthSystem.ChangeHealth(healValue);
    }
}

해결 방법

튜터님의 도움을 받아 해결할 수 있었다.
체력을 담당하는 HealthSystem 스크립트의 Update 함수의 문제였다.

기존 Update 함수의 역할은 캐릭터가 공격을 받았을 때 일정 시간 동안 무적 상태를 유지하게 관리하는 것이다.

  1. PickupHeal.cs 에서 healthSystem.ChangeHealth(healValue) 를 통해
    HealthSystem.cs 의 ChangeHealth 함수를 실행한다.

  2. 게임이 시작될 때, timeSinceLastChange 는 float.MaxValue 로 초기화 해주기 때문에,
    첫번째 if 문을 통과하여 timeSinceLastChange 는 0f 로 바뀌지만,
    체력을 회복하기 때문에 isAttacked 는 false 이다.
    (만약 데미지를 입었다면 isAttacked 는 True, timeSinceLastChange = 0f)

  3. 포션을 먹은 후, isAttacked 는 false 값으로 바뀌지 않기 때문에,
    Update() 의 조건식을 만족할 수 없기 때문에, 무적 상태가 끝나지 않는다.

따라서, Update() 문의 조건식에서 isAttacked 를 제거해줘 해결할 수 있었다.

// HealthSystem.cs
private void Update()
{
	if(isAttacked && timeSinceLastChange < healthChangeDelay)
	{
		timeSinceLastChange += Time.deltaTime;
		if(timeSinceLastChange >= healthChangeDelay )
        {
			OnInvincibilityEnd?.Invoke();
			isAttacked = false;
		}
    }
}

public bool ChangeHealth(float change)
{
	if(timeSinceLastChange < healthChangeDelay) // 일시적인 무적 시간으로 공격받지 않음
	{
		return false;
    }

	timeSinceLastChange = 0f;
	CurrentHealth += change;
    CurrentHealth = Mathf.Clamp(CurrentHealth ,0, MaxHealth);

	if(CurrentHealth <= 0f) // 죽었을 때
    {
	    CallDeath();
		return true;
    }

	if(change >=0)
	{
		OnHeal?.Invoke();
	}
	else
	{
		OnDamage?.Invoke();
		isAttacked = true;

		if (damageClip)
			SoundManager.PlayClip(damageClip);
	}
	return true;
}

결과

체력을 올려주는 포션을 먹은 뒤에도, 정상적으로 체력이 닳는 것을 확인할 수 있었다.


트러블 슈팅 (2)

상황

The referenced script on this Behaviour(Game Object) is missing!

게임을 플레이할 때마다, 콘솔창에 다음과 같은 문구가 떴다.
플레이하는 데 지장은 없지만, 해결해보고 싶었다.


분석 (1)

DustParticles 는 캐릭터가 이동할 때마다, 발생하는 파티클 시스템이다.
이동하는 Walk 애니메이션에 이벤트를 추가하여 해당 스크립트의 CreateDustParticles() 를 실행하였다.

Animation Event 1Animation Event 2

public class DustParticleControl : MonoBehaviour
{
    [SerializeField] private bool createDustOnWalk = true;
    [SerializeField] private ParticleSystem dustParticleSystem;

    public void CreateDustParticles()
    {
        if (createDustOnWalk)
        {
            dustParticleSystem.Stop();
            dustParticleSystem.Play();
        }
    }

}

분석 (2)

Player 의 자식으로 MainSprite 를 두고,
MainSprite 의 컴포넌트에 DustParticleControl 스크립트를 붙였다.
Prefabs 폴더에 있는 DustParticles 를 DustParticleControl 컴포넌트에 드래그 앤 드롭 해주었다.


해결 방안

DustParticles 프리팹을 뜯어 확인했을 때, 다음과 같은 삭제된 스크립트가 존재하였다.

The referenced script on this Behaviour(Game Object) is missing!
객체에 붙어 있는 스크립트가 삭제되어 Missing 이 발생한다는 뜻이었고,
실제로 프리팹에는 삭제된 스크립트가 존재하였다.

해당 스크립트를 삭제해준 뒤, 플레이를 했을 때 더 이상 오류 메시지는 발생하지 않았다.


TIL 마무리

첫번째 트러블 슈팅의 경우, Update 함수의 조건문에서 isAttacked 를 빼면 된다는 해결방안을 들었다.

TIL 을 작성하면서, 아이템을 먹고 PickUpHeal 스크립트를 지나,
캐릭터의 healthSystem 의 ChangeHealth 함수를 지나는 과정을 따라가보며,
Update 문의 isAttacked 조건을 지웠을 때 정상적으로 작동되는지를 이해해보았다.

그냥 그런가보다 하고 넘어갔다면, 강의를 2개, 3개 들을 수도 있는 시간이라 아깝기도 했지만,
또 다시 이런 실수를 반복하지 않기 위한 투자라고 생각하면서 TIL 을 마쳐야겠다.

profile
안녕하세요 게임 개발하는 MINO 입니다.

0개의 댓글