[타워디펜스게임] #7. 유닛 클래스

치치·2025년 1월 13일
0

타워디펜스게임

목록 보기
7/18
post-thumbnail

오늘의 목표 !

  • 유닛의 공통된 정보를 추상클래스로 만든 뒤, 각각의 유닛들의 자식 클래스를 생성

  • 각각의 유닛 클래스들에 정보를 저장

    유닛들은 공통된 스탯을 가지고 있고 공격과 죽는 것을 다 다른 조건에서 동일하게 처리할 수 있을 거 같아서 추상클래스로 묶어보자는 생각을 했다
    UnitStat 부모클래스를 만들고 유닛5개의 스크립트를 개별적으로 작성한 뒤 UnitStat 클래스를 상속받게 했다

  • 처음 만들어 보는 게임이라 그런지,,, 스크립트 하나에 자꾸 여러 기능을 다 넣어버리고 있다... 애니메이션도 따로 스크립트를 작성하는 게 더 나을 거 같은데 일단 그냥 스파게티 코드여도 내가 생각하고 시도하는걸로 가보기로 했다

유닛정보 관련

UnitStat (부모) 스크립트

  • 부모 스크립트에서 중요하게 볼 몇개의 함수, 하나씩 차례로 살펴보자
  1. Start 함수 : 각 유닛들의 현재 HP를 최대치로 설정
  2. SetHPBar 함수 : 유닛들의 HP바 슬라이더 가져와서 초기화
  3. TakeDamage함수 : 적에게 타격을 입으면 유닛의 HP 감소
  4. PlayDeathAnimation함수 : 죽음 애니메이션
  5. Die함수 : 유닛이 죽은 뒤 처리 (삭제)

  • 부모클래스에서 정의한 것들은 자식클래스에서 밖에 사용하지 않을것이기 때문에 변수들은 모두 protected와 private접근 지정자를 사용하였다
  • 그리고 추상클래스의 부모는 실제로 유니티 객체에 직접 스크립트를 넣어줄 수 없음!!! 그냥 정의만 해두고 자식 스크립트를 사용해야한다
  • SerializeField로 설정한 이유
    -> 현재체력을 유니티 인스펙터창에서 확인하기 위해서
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;


// 부모 추상 클래스 UnitStat

// 객체를 만들 수 없음
public abstract class UnitStat : MonoBehaviour
{
    [SerializeField] protected int maxHealth;       // 최대 체력

    [SerializeField] protected int currentHealth;   // 현재 체력

    protected Slider HPslider;                      // 체력 슬라이더

    protected Animator animator;                   // 애니메이터 추가
    private bool isDying = false;                  // 죽음 상태 플래그

Start( )

  • 현재 체력을 최대체력으로 설정하고 유닛의 애니메이터 컴포넌트를 가져온다
  • HP바 슬라이더와 현재 체력수치를 연동해주기 위해서 슬라이더 수치를 지정해주었다
protected virtual void Start()
{
    currentHealth = maxHealth;
    animator = GetComponent<Animator>();       // Animator 컴포넌트 가져오기

    if (HPslider != null)
    {
        HPslider.maxValue = maxHealth;
        HPslider.value = currentHealth;
    }

    //Debug.Log($"MonsterStat 초기화: MaxHealth={maxHealth}, CurrentHealth={currentHealth}");
}

SetHPBar( Slider slider )

  • 이 SetHPBar( )함수는 Unit스크립트 내에서 유닛과 유닛의 체력바를 연결할때, 그 수치를 적용하기 위해 사용된다
public void SetHPBar(Slider slider)
{
    //Debug.Log("SetHPBar 호출됨");
    HPslider = slider;

    if (HPslider != null)
    {
        HPslider.maxValue = maxHealth;
        HPslider.value = currentHealth;
    }
    else
    {
        //Debug.LogError("슬라이더가 null입니다!");
    }
}

TakeDamage( int damage )

  • 인자로 들어온 값만큼 데미지를 입게 설정해두었다 ( 0 이하로 떨어지진 않게)
    -> 인자로 들어오게 될 값은 나중에 MonsterGizmo스크립트쪽에 작성해두었다
    -> 각각의 몬스터마다 공격력이 다르기 때문에 그 수치를 각 몬스터 공격력만큼 인자로 받아오게 설정해두었다

  • 현재체력에서 계속 데미지만큼 수치를 까게되면 슬라이더 수치에도 적용되게 하였다

  • 현재 체력이 0과 같거나 작아진다면 죽음 애니메이션 함수를 호출한다

public void TakeDamage(int damage)
{
    if (isDying) return; // 죽음 중일 때 추가 데미지 방지

    currentHealth -= damage;
    currentHealth = Mathf.Clamp(currentHealth, 0, maxHealth);

    if (HPslider != null)
    {
        HPslider.value = currentHealth;
    }

    if (currentHealth <= 0)
    {
        PlayDeathAnimation();
    }
}

PlayDeathAnimation( )

  • 현재 체력이 0과 같거나 작을때 실행
// 죽음 애니메이션 실행
protected virtual void PlayDeathAnimation()
{
    if (animator != null)
    {
        isDying = true;
        animator.SetTrigger("Die"); // Die 트리거 설정
        StartCoroutine(WaitForDeathAnimation());
    }
    else
    {
        Die(); // 애니메이터가 없으면 바로 Die 호출
    }
}

  • 외에도 부모 스크립트에 공통적으로 사용되는 변수들을 작성해두었지만, 현재로써는 아직 사용되고 있지 않아서 블로그에는 작성하지 않았다
    -> 각 유닛의 정보

Die( ) & 애니메이션 지속시간 -> 코루틴

  • Die( )함수가 호출되면 유닛이 죽는거기 때문에 객체를 파괴하고 유닛의 체력바도 비활성화
    -> 체력바를 파괴하지 않는이유는 프리팹으로 생성된거기 때문에 비활성화로 작성함
  • 수정사항
    -> 코드에 몬스터의 카운트를 감소되는 사항을 유닛의 카운트를 감소되게 해야함..
    -> static으로 선언한 unitCount의 수를 감소하고 UI를 업데이트 해야할듯
    -> 지금은 유닛이 죽으면 몬스터의 수가 감소되게 되있음
protected virtual void Die()
{
    MonsterCount.Instance.DecreaseCount(); // 몬스터 카운트 감소 <- 이거 왜 여기있냐..?
    Debug.Log($"{gameObject.name} 사망!");
    Destroy(gameObject);
    HPslider.gameObject.SetActive(false);
}

private IEnumerator WaitForDeathAnimation()
{
    yield return new WaitForSeconds(1.5f); // 애니메이션 지속 시간
    Die();
}


Unit00010 : UnitStat (자식 스크립트)

  • 부모에 정의된 함수들과 변수를 바탕으로 자식 스크립트에서 사용한다
  • 이제 각 유닛은 UnitStat 스크립트를 상속받고 유닛마다 고유의 정보들을 작성해주면 된다
  • Unit00010의 최대 체력값을 설정하고 Start함수를 호출해서 초기화한다
  • 이 스크립트가 붙어있는 유닛이 죽게되면 Die함수 호출되고 해당 유닛이 파괴된다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 상속받은 자식 클래스
public class Unit00010 : UnitStat
{
    protected override void Start()
    {
        maxHealth = 50;
        base.Start(); // 부모 클래스의 Start 호출

    }
    // 애니메이션 이벤트에서 호출
    protected override void Die()
    {
        base.Die(); // 기본 Die 동작 실행
    }

Unit00020 : UnitStat (자식 스크립트)

  • 스크립트 동일
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Unit00020 : UnitStat
{
    protected override void Start()
    {
        maxHealth = 50;
        base.Start(); // 부모 클래스의 Start 호출

    }
    // 애니메이션 이벤트에서 호출
    protected override void Die()
    {
        base.Die(); // 기본 Die 동작 실행
    }


최종 체력바의 모습

유닛이 공격받아서 체력이 까이는 상황을 유니티 인스펙터창에서 확인할 수 있다
나중에 MonsterGizmo 스크립트에서 공격범위에 들어오면 몬스터가 공격액션을 취하고 유닛에게 데미지를 입히는 것까지 할 것이다!

profile
뉴비 개발자

0개의 댓글