[Unity] 자습서 7장 - 적 공격, 사망 이벤트

2023. 3. 2. 20:18·개발/Unity

이번 장에서는 몬스터와 플레이어에게 hp를 부여하고 서로의 공격과 사망 이벤트를 구현할 것이다.

 

적의 공격 능력

전 장에서 몬스터가 플레이어와 일정 거리 이내로 좁혀짐녀 공격 애니메이션을 수행하는 로직을 구현했다. 이제 실제로 데미지를 입혀야 하는데, 주인공에게 데미지를 입히는 방법은 1. 물리적인 타격, 2. 공격 주기의 수치상의 데미지 이렇게 두 가지 방식이 있다. 첫 번째 방식인 물리적인 타격을 통해 데미지를 입히는 방식으로 구현을 해보도록 하겠다. 

 

물리적인 충돌을 발생시키기 위해 몬스터의 양쪽 손에 Sphere Collider와 Rigidbody를 추가해주고 Collider의 Is Trigger 속성에 체크해 몸체에 있는 Capsule Collider 와의 물리적인 간섭을 없애고 Rigidbody의 Is Kinematic 속성에 체크해 물리 시뮬레이션을 연산하지 않게 설정해주었다. 

 

공격을 당하는 주인공 입장에서 어떤 Collider가 충돌했는지 알기 위해 몬스터의 양 손에 PUNCH 태그를 지정해주었다. 주인공에게도 Capsule Collider 와 Rigidbody를 추가해주어 충돌 이벤트가 발생하도록 하였다.

그 후 주인공의 스크립트에서 ConTriggerEnter 함수에서 충돌한 Collider가 PUNCH 태그 이면 hp를 차감시키도록 하였다.

 

// 충돌한 Collider의 IsTrigger 옵션이 체크됐을 때 발생
    private void OnTriggerEnter(Collider other)
    {
        // 충돌한 Collider가 몬스터의 PUNCH이면 player의 HP 차감
        if(currHp >= 0.0f && other.CompareTag("PUNCH"))
        {
            currHp -= 10.0f;
            Debug.Log($"Player hp = {currHp / initHp}");

            // Player의 생명이 0 이하이면 사망 처리
            if(currHp <= 0.0f)
            {
                PlayerDie();
            }
        }
    }

 

몬스터 공격 중지

주인공 캐릭터의 hp가 0 이하일 때는 게임이 끝나게 되므로 몬스터에게 주인공이 죽었음을 알려야 한다. 죽음을 알리면 몬스터는 공격을 멈추고 추적도 정지하게 된다.

전달 방법은 GameObject.FindGameObjectsWithTag(string tag)를 이용하여 해당 태그로 지정된 모든 게임오브젝트를 Array 타입으로 반환시킨다. 몬스터에게 MONSTER 태그를 새로 지정해주고 주인공 스크립트에서

GameObject[] monsters =GameObject.FindGameObjectsWithTag("MONSTER"); 로 모든 몬스터를 태그로 검색한 후 배열에 저장한다. 

이렇게 저장된 몬스터들에게 특정 함수를 실행시키라고 전달해 주어야 하는데, 몬스터 스크립트에서 우선 실행할 함수를 하나 만들었다.

 

void OnPlayerDie()
    {
        // 몬스터의 상태를 체크하는 코루틴 함수를 모두 정지시킴
        StopAllCoroutines();

        // 추적을 정지하고 애니메이션을 수행
        agent.isStopped = true;
        anim.SetFloat(hashSpeed, Random.Range(0.8f, 1.2f));
        anim.SetTrigger(hashPlayerDie);
    }

 

OnPlayerDie 함수가 호출되면 몬스터는 모든 공격, 추적 루틴에서 벗어나고 게임 종료 애니메이션을 수행한다. 게임 종료 애니메이션으로는 싸이의 강남스타일을 추도록 설정하였다. 게임을 실행한 후 주인공의 hp가 0이 됐다는 로그가 콘솔창에 뜨면 몬스터들이 다같이 춤을 추는 모습을 확인할 수 있다.

 

 

 

델리게이트(Delegate)

주인공이 사망하면 모든 몬스터들이 공격을 중지할 수 있도록 전달해주어야 하는데 이벤트 구동 방식을 통해 전달해 주었다. 이벤트(Event) 란 특정한 조건을 만족하면 자동으로 알려주는 메시지를 의미한다. 주인공이 사망했을 때 그것을 알리는 이벤트를 생성하면 시스템에서 이를 자동으로 통보하고, 이 이벤트에 연결된 모든 몬스터에서 정해진 동작을 수행한다.

 

델리게이트는 함수(메서드)를 참조하는 변수를 의미한다. 함수(메서드)를 저장할 수 있는 일종의 변수라고 생각하면 된다. C++의 포인터와 같은 의미이다.

델리게이트를 사용하려면 우선 델리게이트를 선언하고, 해당 델리게이트 타입의 변수를 선언한다. 선언한 델리게이트 명이 변수의 타입이 되는 것이다. 이제 이 델리게이트를 이용해서 델리게이트와 이벤트 함수를 선언하고 이 이벤트를 호출할 것이다.

 

// 델리게이트 선언
    public delegate void PlayerDieHandler();
    // 이벤트 선언
    public static event PlayerDieHandler OnPlayerDie;
    
     // Player의 사망 처리
    void PlayerDie()
    {
        Debug.Log("Player Die !");

        // 주인공 사망 이벤트 호출(발생)
        OnPlayerDie();
    }

 

이벤트를 선언하고 발생시킬 로직을 완성했으면 몬스터 스크립트에서 발생하는 이벤트에 반응할 특정 함수를 연결한다. 이벤트는 반드시 스크립트의 활성화 시점에 연결하고, 비활성화될 때 해제해야 한다.

 

// 스크립트가 활성화될 때마다 호출되는 함수
    private void OnEnable()
    {
        // 이벤트 발생 시 수행할 함수 연결
        PlayerCtrl.OnPlayerDie += this.OnPlayerDie;
    }

    // 스크립트가 비활성화될 때마다 호출되는 함수
    private void OnDisable()
    {
        // 기존에 연결된 함수 해제
        PlayerCtrl.OnPlayerDie -= this.OnPlayerDie;
    }

 

이벤트와 연결과 해지는 반드시 OnEnable() 과 OnDisable() 함수에서 처리해야 한다.

 

 

몬스터의 사망 처리

이제 마지막으로 몬스터의 사망 처리를 구현할 것이다. 스크립트에 hp 변수를 지정하고 OnCollisionEnter 함수에서 hp가 0이하인지 판단해 사망했는지 판단한다. 그리고 마지막으로 애니메이션도 삽입하여 완성한다.

 

IEnumerator MonsterAction()
    {
        while (!isDie)
        {
            switch (state)
            {
                // 사망
                case State.DIE:
                    isDie = true;
                    // 추적 정지
                    agent.isStopped = true;
                    // 사망 애니메이션 실행
                    anim.SetTrigger(hashDie);
                    // 몬스터의 Collider 컴포넌트 비활성화
                    GetComponent<CapsuleCollider>().enabled = false;
                    break;
            }
            yield return new WaitForSeconds(0.3f);
        }
    }
    
    private void OnCollisionEnter(Collision collision)
    {
        if (collision.collider.CompareTag("BULLET"))
        {
            // 몬스터의 hp 차감
            hp -= 10;
            if(hp <= 0)
            {
                state = State.DIE;
            }
        }
    }

 

스크립트를 수정한 후 사망 애니메이션을 연결해주고 게임을 실행하면 아래와 같이 몬스터의 사망 구현이 완료된다.

 

 

이렇게 몬스터 제작부분이 끝이 났다. 메카님 애니메이션으로 FSM화 했으며 내비게이션을 응용해 추적 루틴을 구현했다. 

또한 델리게이트 문법을 활용해 이벤트를 사용해보았다. 다음 장에서는 게임의 전반적인 기능을 구현해보겠다.

 

 

'개발 > Unity' 카테고리의 다른 글

[Unity] Unity3D 마우스 좌표에 미사일 폭격하기  (2) 2023.03.13
[Unity] 자습서 6장 - 적 캐릭터 구현  (0) 2023.02.28
[Unity] 자습서 5장 - 코루틴, 오디오  (0) 2023.02.24
[Unity] 자습서 4장 - 총 발사 로직(Mac)  (0) 2023.02.22
[Unity] 자습서 3장 - 캐릭터 제작(Mac)  (0) 2023.02.21
'개발/Unity' 카테고리의 다른 글
  • [Unity] Unity3D 마우스 좌표에 미사일 폭격하기
  • [Unity] 자습서 6장 - 적 캐릭터 구현
  • [Unity] 자습서 5장 - 코루틴, 오디오
  • [Unity] 자습서 4장 - 총 발사 로직(Mac)
Majangnan
Majangnan
  • Majangnan
    개발 모코코
    Majangnan
  • 전체
    오늘
    어제
    • 분류 전체보기 (66) N
      • 개발 (65) N
        • C# (10)
        • SQL (3)
        • Unity (8)
        • Unreal (10)
        • C++ (3)
        • Server (1)
        • DX11 (8)
        • 알고리즘 (21) N
  • 블로그 메뉴

    • 홈
    • 방명록
    • 깃허브
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    C#
    프로그래머스
    언리얼
    상속
    코딩테스트
    DirectX11
    Mecanim
    알고리즘
    MAC
    백준
    blueprint
    dx3d
    sql
    UnReal
    Unity
    슈팅게임
    3dlight
    블루프린트
    DX11
    c++
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Majangnan
[Unity] 자습서 7장 - 적 공격, 사망 이벤트
상단으로

티스토리툴바