ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Unity]유니티 입문하기 6-13(적 피격 판정)
    프로그래밍 2023. 8. 24. 20:09

    이전 글에서 드디어 적에 해당하는 오브젝트를 만들고, 클래스를 채워봤습니다.

    이번에는 아군의 공격에 맞았을 때 반응하도록 피격 판정을 만들어봅시다.


    일단, 바로 적을 향해 총알을 발사해 봅시다.

    현재는 적 오브젝트와 총알이 충돌하여 체력이 감소하는 기능이 구현되어있지 않으므로, 그림과 같이 총알이 적을 그냥 지나치게 됩니다.

     

    그럼 피격 판정을 만들기 위해 어떤 과정이 필요한 지 생각해 봅시다.

    1. 적과 총알이 충돌한다.
    2. 충돌이 발생하면 적의 체력이 감소한다.
    3. 충돌이 발생하면 투사체가 소멸하고, 체력에 따라 적이 소멸한다.

    충돌 판정

    이 모든 과정을 위해서는, 먼저 총알과 적이 충돌해야 합니다.

     

    우리가 총알의 발사를 위해 RigidBody2D 컴포넌트를 이용했던 것처럼, 오브젝트 간의 충돌을 위해서는 Collider 컴포넌트를 이용합니다.

     

    먼저 Bullet과 Enemy 오브젝트에 각자 모양에 맞는 Colider를 부착해 줍시다.

    둥그런 Knob 스프라이트를 이용했다면 Circle Collider 2D 컴포넌트를 부착하면 됩니다.

    이때, Bullet은 프리팹이므로 프리팹 모드로 들어가서 수정하는 것을 잊지 맙시다.

    (저는 비행기 모양을 채택했으므로, Enemy에는 Box Collider 2D를 부착했습니다.)

     

    Collider 컴포넌트들은 부착하면 자동으로 스프라이트에 맞춰서 크기가 조정됩니다.

    콜라이더는 이렇게 초록색 선으로 확인할 수 있습니다. 콜라이더가 부착되어 있는 동안, 이 초록색 선이 충돌의 기준이 되는 것이죠.

     

    이렇게 콜라이더를 부착한 뒤 다시 총알을 발사해 보면, 아래와 같이 총알과 비행기가 충돌하여 앞으로 나아가지 못하는 것을 볼 수 있습니다.

    그러면 이제 충돌을 인식하고, 적의 체력이 감소하도록 만들어보죠.

     

    체력 감소

    충돌이 일어나게 설정하는 것까지는 끝냈지만, 충돌 계기로 임의의 코드를 실행하고자 한다면, 충돌을 인식할 수 있어야겠죠.

    스크립트에서 두 오브젝트 간의 충돌을 감지하는 메서드는 OnCollisionEnter2D() 메서드입니다.

    이 메서드를 스크립트에 추가하게 되면, 해당 오브젝트가 다른 오브젝트와 충돌하였을 때 이 메서드가 실행되게 됩니다.

     

     

    public void private void OnCollisionEnter2D(Collision2D coll) {
            Debug.Log("충돌");
        }

    테스트를 위해 위와 같은 코드를 Enemy 클래스에 넣고 게임을 실행한 뒤 총알을 발사해 보면 이렇게 코드가 실행되는 것을 확인할 수 있습니다.

     

    충돌을 감지하는 메서드가 OnCollisionEnter2D()만 있는 것은 아닙니다.

     

    충돌을 감지하는 메서드에는

    충돌 시점에 실행되는 OnCollisionEnter2D(),

    두 콜라이더가 접촉 중인 동안 계속 실행되는 OnCollisionStay2D(),
    두 콜라이더가 떨어지는 순간에 실행되는 OnCollisionExit2D()
    의 3가지가 있습니다.

     

    지금은 총알이 적군과 충돌하는 순간에 코드가 작동해야 하므로,  OnCollisionEnter2D() 메서드를 이용했습니다.

     

    그럼, 위에서 작성한 충돌을 인식하는 코드를 바로 체력을 감소시킨 뒤, 감소된 체력을 출력하는 코드로 수정해 봅시다.

    public void OnCollisionEnter2D(Collision2D coll) {
        TakeDamage(10);
        Debug.Log("Health: "+health);
    }

    저는 저번 글에서 만든 메서드인 TakeDamage() 메서드를 이용해 봤지만, 직접 health 변수를 감소시켜도 무방합니다.

     

    바로 코드를 적용한 뒤 게임을 실행해 보면, 총알이 적군에 충돌할 때마다 위와 같이 감소된 체력이 출력되는 것을 확인할 수 있습니다.

     

    충돌 후 총알 삭제

    위에서 메서드들을 테스트하다 보면, 단순히 적군과 총알끼리만 부딪히는 것이 아니라 총알과 총알끼리도 부딪혀 뒤에 오는 총알이 앞에서 먼저 온 총알에 막혀 적에게 명중하지 못하는 것을 볼 수 있습니다.

    이를 방지하기 위해, 총알이 적에게 충돌하면 총알이 없어지도록 해봅시다.

     

    바로 예제 코드부터 보도록 하죠.

    public void OnCollisionEnter2D(Collision2D coll) {
        TakeDamage(10);
        Debug.Log("Health: "+health);
        coll.gameObject.SetActive(false);
    }

    아까와 크게 변한 것은 없습니다.

    다만, 아까 언급하지 않고 넘어갔던 매개변수인 coll을 사용한 것을 확인할 수 있는데, OnCollisionEnter2D() 메서드에서 인수는 충돌한 오브젝트입니다.

    즉, coll 변수를 통해 우리는 적군 오브젝트와 충돌한 오브젝트에 접근할 수 있다는 뜻이죠.

    그래서 이전에 배웠던 오브젝트를 비활성화시키는 코드를 통해 총알들을 사라지게 할 수 있는 것입니다.

     

    바로 테스트해보면, 계층 구조 창에서 비활성화된 총알들이 남아있는 것을 확인할 수 있습니다.

    물론, 비활성화된 총알들도 이전에 Invoke를 통해 실행해 둔 Destroy() 메서드에 의해, 얼마 안 가 사라집니다.

     

    동시에 위와 같이 콘솔에서는 제대로 체력의 감소가 일어나고 있음을 확인할 수 있죠.

     

    위에서 체력이 감소되는 것을 보면, 체력이 음수로도 한없이 내려가는 모습을 볼 수 있습니다.

    이는 우리가 의도한 바가 아니죠. 체력이 0이 되면 Bullet에서 사용했던 것과 같이 Destroy() 메서드를 이용해 사라지도록 한번 해봅시다.

     

    public void OnCollisionEnter2D(Collision2D coll) {
        TakeDamage(10);
        coll.gameObject.SetActive(false);
        if(health <= 0){
            Die();
        }
    }
    
    void Die(){
        Destroy(this.gameObject);
    }

    체력을 출력하는 부분을 지우고, 조건문을 통해 체력이 0 이하가 되면 Die 메서드를 실행하도록 하였습니다.

    물론 DIe 메서드 또한 만들어주었고요.

     

    바로 코드를 실행한 뒤 총알을 발사하다 보면, 이렇게 게임 뷰에서도 사라지고 , 계층 구조 창에서도 사라진 모습을 볼 수 있습니다.

     

     health의 값이 외부에 공개되어 외부에서 마음대로 수정하게 된다면, 적군이 공격받지 않았는데도 죽은 상태가 되는 등의 문제가 있을 수 있습니다.

    캡슐화에 대해서 공부할 때 배운 속성을 이용해 health 변수를 숨겨봅시다.

    float health = 50.0f;
    
    public float Health{
        get { return health; }
    }

    외부에서는 health 변수를 수정하면 안되므로, set 접근자는 제거해주었습니다.

    추가로, GetHealth() 메서드를 get 접근자로 대체할 수 있게 되었으므로, GetHealth() 메서드도 제거해줍니다.

Designed by Tistory.