본문 바로가기
게임 프로그래밍/게임개발 중급

게임개발 중급(48) - Monster Killer(10)

by jyppro 2023. 6. 9.

Monster Killer(10)

이전엔 몬스터 소환 및 죽음이 동시에 일어나게 하여 두 몬스터가 겹치는 현상이 발생하지 않도록 고쳤습니다. 또한, 무기 생성속도가 느려 게임 진행속도가 전체적으로 느려진 것을 해결하기 위해 딜레이타임을 최소한으로 변경해 주었습니다. 이번에는 부위별 데미지 문제점에 대해 고쳐보는 시간을 갖도록 하겠습니다.

 

부위별 데미지

처음에 의도했던 것은 부위별로 받는 데미지를 다르게 설정하여 공격하는 방식에 다양성을 부여하는 것이 목표였습니다.

하지만, 몬스터가 고정된 상태에서 플레이어만 이동이 가능하게 구현되어 있다보니, 머리부분만 공격하면 된다는 공략법이 존재하는 상황입니다. 이 문제를 해결하려면 고쳐야 할 부분이 상당히 많습니다. 일단 가장먼저 해줘야 할 것은 머리 이외에 다른 부위에도 데미지를 부여하는 것입니다. 하나씩 차근차근 해결해 나가보겠습니다.

 

몬스터 피격부위

정말 다행스럽게도 제가 몬스터로 사용한 해당 에셋의 몬스터는 프리팹안에 몬스터의 구성부위가 전부 세세하게 들어가 있었습니다.

몬스터-구성요소
몬스터 구성요소

왼쪽과 오른쪽의 가슴부터 몸통 다리 발까지 전부 파츠별로 구성이 되어있는 모습입니다. 저는 그래서 이 파츠를 이용해볼 생각입니다. 데미지를 받는 부위를 너무 세분화해서 만들 필요는 없으니 발톱이나 발등 같은 공격이 자주 들어가지 않는 부위들은 대략적으로 상위 부위로 묶어서 처리하는 방식을 사용하겠습니다.

대략적인-부위선정
대략적인 부위선정

저는 왼쪽과 오른쪽 뒷다리 그리고 척추(등)과 꼬리 이렇게 4가지를 부위로 사용하려고 합니다. 그렇다면 이 부위에 공격이  들어왔을 때, 데미지가 다르게 적용되야 한다는 것인데 어떻게 하면 될까요?

 

부위별 콜라이더 적용

기존에는 몬스터 프리팹에 콜라이더를 크게 생성하여 데미지를 판단해 주었지만, 이제 부위별로 콜라이더를 따로 만들어 적용시켜주겠습니다.

부위별-콜라이더
부위별 콜라이더 적용

해당 그림처럼 몬스터의 모양에 맞게 콜라이더를 잘 맞춰서 만들어주시면 됩니다. 나머지 세부위도 똑같이 만들어 줍니다.

그렇게 하면 공격했을 때 판정을 받을 부위는 구현이 되었습니다. 이제 부위별로 데미지가 다르게 들어가도록 만들어 주어야 합니다.

 

부위완성
부위완성

부위별로 콜라이더를 적용시켜 각 부위단위를 만들었습니다. 기존에 있던 콜라이더는 삭제시켰으므로 현재 정면에서는 머리만 공격할 수 있습니다.

 

이제 데미지를 설정해 주어야 하는데 기존에 저희가 사용하던 머리에서 멀어질수록 데미지가 적게 들어가는 방식은 머리 이외에 다른 부위 어느곳을 때리던 데미지가 거의 고정적으로 약하게 들어갔습니다. 하지만 이제는 부위별로 원하는 데미지의 범위를 지정해 줄 수 있습니다. 이제 코드를 살펴보시겠습니다.

 

WeaponController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WeaponController : MonoBehaviour
{
    public GameObject WeaponGenerator;
    public int damage;

    public void Shoot(Vector3 dir) //인자로 3차원 벡터가 입력되고
    {
        GetComponent<Rigidbody>().AddForce(dir); // 들어온 입력벡터 만큼 오브젝트에 힘이 가해진다.
    }
    
    // Start is called before the first frame update
    void Start()
    {
        this.WeaponGenerator = GameObject.Find("WeaponGenerator");
    }

    public void OnCollisionEnter(Collision collision) //다른 물체와 충돌하는 순간
    {
        GetComponent<Rigidbody>().isKinematic = true; //중력의 영향을 무시
        GetComponent<ParticleSystem>().Play(); // particle효과를 실행시킨다.

        if (collision.gameObject.CompareTag("Head")) //몬스터와 충돌하는 경우 데미지
        {
            damage = Random.Range(30,50);
            collision.gameObject.transform.root.GetComponent<MonsterController>().TakeDamage(damage);
            Destroy(gameObject, 0.5f);
        }
        else if (collision.gameObject.CompareTag("L_Leg"))
        {
            damage = Random.Range(25,40);
            collision.gameObject.transform.root.GetComponent<MonsterController>().TakeDamage(damage);
            Destroy(gameObject, 0.5f);
        }
        else if (collision.gameObject.CompareTag("R_Leg"))
        {
            damage = Random.Range(25,40);
            collision.gameObject.transform.root.GetComponent<MonsterController>().TakeDamage(damage);
            Destroy(gameObject, 0.5f);
        }
        else if (collision.gameObject.CompareTag("Body"))
        {
            damage = Random.Range(20,35);
            collision.gameObject.transform.root.GetComponent<MonsterController>().TakeDamage(damage);
            Destroy(gameObject, 0.5f);
        }
        else if (collision.gameObject.CompareTag("Tail"))
        {
            damage = Random.Range(10,50);
            collision.gameObject.transform.root.GetComponent<MonsterController>().TakeDamage(damage);
            Destroy(gameObject, 0.5f);
        }
        else if (collision.gameObject.tag == "terrain")
        {
            Destroy(gameObject);
        }
    }
}

코드가 조금 지저분하긴 하지만, 현재 생각나는 방법은 태그로 분리해서 처리하는 방법밖에 없었습니다. 기존에 머리판정을 담당하던 HeadPoint 오브젝트를 몬스터 하위로 집어넣어주고, 다른 부위와 마찬가지로 콜라이더를 만들어 줍니다. 그리고 자식 오브젝트에서 MonsterController가 들어있는 최상위 부모의 오브젝트에 접근해야 하기 때문에 transform.root.GetComponent를 사용해 줍니다. 데미지는 머리가 가장 좋게 하되, 다른 부위와 차이가 크지않도록 하고, 최대치가 머리가 가장 크게 갖도록 하여 부위별 데미지의 밸런싱을 하였습니다. 지금은 몬스터 하나에게만 적용시켰지만, 똑같이 다른 몬스터들에게도 적용시켜 주면 됩니다.

 

여기서 약간의 노가다 작업이 필요한데, 다른 몬스터들도 마찬가지로 프리팹에 태그와 각 부위별 콜라이더 그리고 헤드포인트까지 전부 추가해주어야 합니다. 그나마 다행인 것은 현재 소환되는 몬스터들의 형태와 크기가 같아서 콜라이더를 그대로 복사붙이기 하면 됩니다.

 

이제 모든 준비가 끝났다면 실행을 해보도록 하겠습니다.

 

부위별 데미지 확인

머리공격
머리공격

head를 맞추었을 때, 30에서 50의 사이값인 47의 데미지가 들어갔습니다.

 

몸통공격
몸통공격

body를 공격했을 때, 53의 체력에서 26이 되었으니 20에서 35사이값인 27의 데미지가 들어갔습니다. 첫번째 몬스터의 체력이 얼마 남지 않았으니 다음 몬스터로 양쪽다리와 꼬리를 공격해 보겠습니다.

 

왼쪽다리-공격
왼쪽다리 공격

L_Leg를 공격했을 때, 25에서 40사이의 최소값인 25의 데미지가 들어갔습니다.

 

오른쪽다리-공격
오른쪽다리 공격

R_Leg를 공격했을 때, 245에서 217로 줄었습니다. L_Leg와 마찬가지로 25와 40사이값인 28의 데미지가 들어갔습니다.

 

꼬리공격
꼬리공격

Tail을 공격했을 때, 10에서 50의 사이값 중 최소값인 10의 데미지가 들어갔습니다. 꼬리는 최소데미지가 낮지만, 최대치가 머리와 같도록 하여 머리의 중요도를 분산시켜 주었습니다.

 

<NEXT>

오늘은 몬스터의 부위별로 데미지를 적용시키는 방법에 대해서 알아보았습니다. 저같은 경우는 에셋으로 가져온 몬스터 프리팹에 이미 부위가 존재했기 때문에 해당방식으로 만들 수 있었지만, 만약 부위가 나눠져 있지 않은 몬스터라면 조금 더 어렵고 복잡한 방식을 사용해야 할 수도 있을 것 같습니다. 다음은 데미지를 시각적으로 표시하는 방법에 대해서 다뤄보겠습니다. 감사합니다.