몬스터가 데미지를 입을 때 체력바가 줄어드는 부분만 있었는데

입힌 데미지 까지 표시 해주기로 했다.

 

이미 데미지를 받아서 HPBar에 넘겨주고 있었기 때문에 관련 코드들을

활용하면 되겠다고 생각했다.

 

해서 구현한 코드

public class TakeDamageUI : MonoBehaviour
{
    private EnemyHealthSystem _enemyHealthSystem;
    private float _duration = 1.5f;

    private void Awake()
    {
        _enemyHealthSystem = GetComponentInParent<EnemyHealthSystem>();
    }

    public IEnumerator DamageUI(TextMeshProUGUI damageAmountTxt)
    {
        damageAmountTxt.color = new(1, 0, 0, 1);

        damageAmountTxt.text = "-" + _enemyHealthSystem.DamageAmount.ToString();
        damageAmountTxt.transform.DOMoveY(0.5f, _duration, false).SetRelative(true);
        damageAmountTxt.DOFade(0, _duration);
        yield return new WaitForSeconds(_duration);
        damageAmountTxt.gameObject.SetActive(false);
    }
}

 

이번에도 역시 DOTween을 이용해서 텍스트의 알파값을 0으로 조정하고

위치를 위로 상승시키는 연출을 해보았다.

 

그리고 코루틴을 받는 텍스트들

public class TakeDamageText : MonoBehaviour
{
    private TakeDamageUI _takeDamageUI;
    public TextMeshProUGUI DamageAmountTxt;
    private Vector3 _baseTransform;

    private Coroutine _coroutine;

    private void Awake()
    {
        _takeDamageUI = GetComponentInParent<TakeDamageUI>();
        _baseTransform = transform.localPosition;
    }

    private void OnEnable()
    {
        transform.localPosition = _baseTransform;
        if ( _coroutine == null )
        {
            _coroutine = StartCoroutine(_takeDamageUI.DamageUI(DamageAmountTxt));
        }
    }

    private void OnDisable()
    {
        _coroutine = null;
    }
}

 

Enable 과 Disable을 사용해 코루틴을 돌려주고 있다.

 

이제 텍스트를 데미지가 입었을 때 하나씩 켜주기만 하면 된다.

public class EnemyHealthSystem : MonoBehaviour
{
	...

    public void TakeDamage(float damage) //데미지를 입었을 때 호출되는 메서드
    {
        Hit = true;
        if (Health == 0) return;

        if (_coroutine != null) 
        {
            StopCoroutine(_coroutine);
            _coroutine = null;
        }

        DamageAmount = damage; //받은 데미지를 Text로 전달하기 위한 변수
        if (TakeDamageText.activeSelf) //1번 텍스트가 켜져 있을 경우
        {
            TakeDamageText2.SetActive(true); //이미 1번이 켜져있기 때문에 다음으로 받는 데미지를 2번이 가져간다.
        }
        TakeDamageText.SetActive(true);

        Health = Mathf.Max(Health - damage, 0); //실제 데미지가 몬스터 체력에 적용되는 부분

        _enemy._stateMachine.ChangeState(_enemy._stateMachine.ChasingState); //데미지를 입으면 거리 상관없이 플레이어를 추격하기 위한 코드

        if (Health == 0) //죽었을 때
        {
            IsDead = true;
            OnDie.Invoke();
            OnQuestTargetDie?.Invoke(_enemySO.EnemyID);
        }
    }
    
}

 

현재는 공격 딜레이 같은 부분을 고려해서 2개의 텍스트를 돌리면 되지만

텍스트가 동시에 많이 사용된다고 하면 if문 만으로 조건을 정하는게 불가능에 가깝기 때문에

개선의 여지가 있다고 느껴진다.

 

코드를 적용한 게임 화면

 

 


 

 

[기술면접 연습]

인터페이스와 추상클래스의 차이를 설명해주세요.

 

인터페이스를 상속 받은 클래스는 인터페이스에 정의된 모든 맴버를 구현해야 하고

일반 맴버를 포함할 수 없는 반면 

추상클래스에서는 일반 맴버를 포함 한 일부 맴버만 구현해도 괜찮습니다.

그리고 인터페이스는 여러개의 클래스의 부모로 있을 수 있지만

추상클래스에서는 단일 상속만을 지원합니다.

 

사용되는 목적 또한 다른데 인터페이스는 클래스가 해당 계약을 준수하도록 강제하고

다른 클래스와의 상호 작용을 표준화 함으로서 코드를 유연하게 만들어줍니다.

추상클래스는 관련된 클래스들 간의 공통된 구현을 공유하고자 할 때 사용되며

일반적으로 상속을 통해 클래스들 간의 코드 재사용을 촉진합니다.

반응형