Health 스크립트
플레이어와 적이 공통적으로 사용하는 hp 스크립트입니다. 기본적인 체력을 설정하고 TakeDamage함수를 통해 데미지를 입은 만큼 체력을 줄입니다. 그리고 OnDie 이벤트를 선언하고 체력이 0이 되면 이벤트를 실행합니다.
public class Health : MonoBehaviour { [SerializeField] protected int maxHealth = 100; public int health { get; private set; } public event Action OnDie; public bool IsDead => health == 0; protected virtual void Start() { health = maxHealth; } public virtual void TakeDamage(int damage) { if (health == 0) return; health = Mathf.Max(health - damage, 0); if (health == 0) OnDie?.Invoke(); } }
Enemy의 스크립트와 연결
Enemy 스크립트에 Health 가져와서 Health의 OnDie이벤트에 실행될 함수를 연결 시켜줍니다.
public Health EnemyHealth { get; private set; EnemyHealth = GetComponent<Health>(); private void Start() { EnemyHealth.OnDie += OnDie; } void OnDie() { Controller.enabled = false; Animator.SetTrigger("Die"); enabled = false; }
이렇게 OnDie라는 함수를 Enemy에 만든다음 캐릭터의 HP가 0이 되면 실행되도록 연결합니다. 이렇게 되면 적의 HP가 0이 되면 컨트롤러를 비활성화 시키고 Die 트리거를 켜서 애니메이션을 실행한 후 적이 죽었으므로 Enemy스크립트를 비활성화해서 안움직이게 합니다.
TakeDamage
플레이어의 총알에 Health의 TakeDamage를 통해 준 데미지 만큼 맞은 오브젝트의 HP를 감소시킵니다.
private void OnCollisionEnter(Collision collision) { if (collision.gameObject.tag != "Bullet") { if (collision.transform.TryGetComponent(out Health health)) { health.TakeDamage((int)damage); } gameObject.SetActive(false); } }
TryGetComponent(out Health health)로 충돌한 오브젝트에서 Health 컴포넌트를 가져오려 시도하고, 해당 컴포넌트가 있는 경우 가져오고, 없으면 null을 반환합니다. Health 컴포넌트를 가져오는 데 성공하면 Health 컴포넌트의 TakeDamage 메서드를 호출하여 데미지를 입힙니다.
이렇게 총에 맞아서 죽는 모션이 잘 실행됩니다.
적이 죽었을 때 플레이어에게 다가오는 버그
처음 적의 AI를 만들 때는 스테이트 스크립트 내의 Move()함수를 통해 적의 오브젝트를 움직였는데 나중에 내비메쉬를 추가하고 Move()함수를 쓰지 않아도 움직일 수 있게 되었고 Move함수에 필요한
stateMachine.MovementSpeedModifier = 0f;
MovementSpeedModifier를 0으로 해도 움직이는 현상을 발견했다.
팀원들과 얘기하며 고민한 결과 내비메쉬와 Move()함수 적을 움직이는 기능이 두개가 있다는 것을 깨닫고 내비메쉬를 아래와 같이 비활성화 하여 문제를 해결하였다.
NavMeshAgent.enabled = false;