Unity/IGDC 입문 프로젝트

7. GameOver 알림

말하는 닭 2023. 9. 2. 14:54

IGDC 입문 프로젝트입니다.

 

 

몬스터가 침략했습니다! 그럼 게임오버가 있어야겠죠?

특정 수의 몬스터가 타워에 도달할 경우 게임오버가 되는 것으로 만들어보겠습니다.

 

 

AllyTower 스크립트를 만들어보겠습니다. 그 다음, 아래 코드를 클래스 안에 넣어줍니다.

private int hp;

public int Hp {
    get { 
        return hp;
    }
    set {
        hp = value;
        if (hp <= 0) {
            Collapse();
        }
    }
}

private void Collapse() {
    GameObject.Find("GameManager").GetComponent<GameManager>().GameOver();
}

Hp는 생긴 것이 뭔가 이상합니다. 바로 프로퍼티(Property)라는 것인데요, get 함수와 set 함수를 따로 만들 필요 없이 묶어놓은 C#에서 제공하는 기능입니다. 

Hp를 호출하면 hp 변수를 반환하고, Hp에 값을 대입, 연산을 하면 set 안의 내용이 실행됩니다.

프로퍼티는 일종의 메소드입니다. value는 프로퍼티의 매개변수라고 생각하시면 됩니다. set할 값을 불러와 hp에 대입시킵니다.

 

만약 hp가 0보다 작거나 같은 시점에 set이 되면, if문 안이 Collapse 함수가 실행됩니다. 

Collapse 함수는 GameManager라는 오브젝트를 찾아 오브젝트 안의 GameManager 클래스를 불러와 GameOver함수를 실행시킵니다. 

 

안타깝지만, 유니티 에디터에서는 프로퍼티를 인스펙터 상에 노출시키지 않습니다. 즉, 에디터 상에서 타워의 체력을 설정을 할 수 없다는 것이죠. 그러므로 GameDatas에 변수를 추가하고 받아오도록 하겠습니다. 

// AllyTower.cs에 다음 함수를 추가합니다.
void Start() {
    Hp = GameObject.Find("GameDatas").GetComponent<GameDatas>().towerHp;
}

// GameDats.cs에 다음 변수를 추가합니다.
public int towerHp;

 

 

지금은 GameManager 클래스도, GameOver 함수도 작성되어 있지 않아 에러가 발생할 겁니다. 

GameManager 클래스를 만들고 GameOver 함수를 지금은 디버그 하나로 작성해둡시다.

using UnityEngine;

public class GameManager : MonoBehaviour
{
    public void GameOver() {
        Debug.Log("게임이 종료되었습니다");
    }
}

그리고 얘가 클래스 형태로만 있으면 안되겠죠? 빈 오브젝트를 만들어 GameManager 클래스를 붙여줍시다. 우리의 경우에는 GameManager를 find하므로, 오브젝트의 이름을 GameManager로 지어줍시다.

 

빈 오브젝트를 생성할 때 이름은 자신의 마음대로 지어도 됩니다. 단, 이 프로젝트에서는 GameObject.Find 함수를 사용하는 일이 빈번합니다. 가능하면 본 글의 내용대로 따라하시길 권장드립니다.
만일 원하는대로 짓고 싶다면, GameObject.Find()의 매개변수를 생성한 오브젝트의 이름과 동일하게 작성해주세요.

 

마지막으로, AllyTower 스크립트를 타워에 붙여줍시다.

 

하지만! 아직 타워의 체력만 구현되었을 뿐, 체력을 깎는 로직이 아직 구현되지 않았습니다.

몬스터가 타워에 도달함을 감지하기 위해, 콜라이더(Collider)를 사용해 충돌감지를 하겠습니다.

 

우선, Ghost에 Rigidbody와 Box Collider를 붙였습니다.

또한, 공간을 차지하지 않도록 IsTrigger에 체크를 하였습니다.

* 사진에 오류가 있습니다. Rigidbody의 Use Gravity를 체크 해제해주세요 *

프로젝트 창의 Ghost 프리팹을 더블 클릭하면, Scene 창에서 프리팹을 자세히 볼 수 있습니다. 

그렇지만... 충돌 감지 영역이 3d 오브젝트보다 많이 큽니다.

Box Collider의 Center와 Size를 잘 조절하여 캐릭터에 적당하게 영역을 설정합니다.

 

조정이 끝났다면, 다시 게임 화면으로 돌아갑시다. 

아래 사진과 같이 하이어리키 창의 '<' 버튼을 클릭하면 작업하던 맵으로 다시 돌아옵니다.

 

 

Ghost만 콜라이더가 붙어서는 감지할 수 없겠죠!

타워에도 콜라이더를 설정합시다.

Rigidbody에 UseGravity를 체크 해제하였습니다. 이제 타워는 중력의 영향을 받지 않습니다. 

Box Collider에도 IsTrigger를 체크했습니다. 

 

 

트리거(Trigger)?

GIF 출처: https://ariel1910.tistory.com/entry/유니티-4-콜라더collider-트리거

 

트리거가 아닐 때가 좌측, 트리거일 때가 우측입니다. 

좌측은 부딪히지만, 우측은 통과해버립니다. 다만, 둘 다 충돌 체크가 됩니다. 


 

이제 충돌 처리 로직을 작성해봅시다.  Enemy 스크립트에 다음 함수를 추가해줍시다. 아마 함수 이름을 작성하면 자동완성이 뜰 것입니다.

private void OnTriggerEnter(Collider other) {
        
}

이 함수는 유니티에서 제공하는 이벤트 함수로, 부딪힌 상대 오브젝트를 매개변수로 가져옵니다.

따라서 아래와 같이 함수 안에 내용을 넣을 수 있습니다. 

if (other.gameObject.CompareTag("AllyTower")) {
    other.gameObject.GetComponent<AllyTower>().Hp--;
}

부딪힌 오브젝트의 gameObject 태그가 AllyTower라면,

오브젝트로부터 AllyTower 클래스를 가져온 후, Hp를 1 깎습니다. 

사실 if문은 아직은 작성할 필요가 없지만, 추후 몬스터가 타워가 아닌 다른 오브젝트와 부딪힐 수도 있습니다. 

그럴 경우 GetComponent는 null을 반환하고, Hp가 Null Reference Execption을 일으킬 수 있습니다. 나중을 위해 작성해놓습니다. 

 

 

그 다음, 태그를 추가해봅시다. 타워를 선택하고, Tag를 클릭 > 하단의 Add Tag... 클릭 > '+' 버튼을 눌러 Tag를 하나 추가해줍니다 > 다시 타워를 선택하고 Tag를 누르면 AllyTower를 설정할 수 있습니다. 

 

 


로직은 여기까지 작성해보겠습니다.

 

GameDatas 오브젝트에 TowerHp를 저는 3으로 설정했습니다. 

 

실행시키면, 3명이 도착했을 때, 콘솔 창에 "게임이 종료되었습니다"라는 문구가 뜨는 것을 볼 수 있습니다.

'Unity > IGDC 입문 프로젝트' 카테고리의 다른 글

9. 공격 타워 배치 및 Cost 기능 구현  (0) 2023.09.03
8. 공격 타워 구현  (0) 2023.09.03
6. 몬스터 스폰 및 이동  (0) 2023.09.01
5. Vector, Transform  (0) 2023.08.31
4. 맵 만들기  (0) 2023.08.31