[TIL] 46일 차 - Unity에서 수류탄 만들기

ChangBeom·2025년 4월 1일

TIL

목록 보기
47/53
post-thumbnail

오늘은 팀프로젝트에서 필요한 수류탄을 만들어 볼 예정이다.


먼저 시작하기 앞서 수류탄이 어떻게 동작하는 지 생각해 볼 필요가 있다.

  1. 던지면 일정 시간 이후에 터진다.
  2. 터질 때 폭발 이펙트가 발생한다.
  3. 폭발범위 안에 있는 몬스터들에게 데미지를 입힌다.
  4. 폭발범위 안에 있더라도 몬스터가 장애물 뒤에 있으면 데미지를 입히지 않는다.
  5. 오브젝트와 폭발 이펙트를 제거한다.

이 중 4번을 어떻게 구현할 지 고민을 많이 했던 것 같다.

그렇게 나온 결론은 다음과 같다.

  1. 수류탄이 터질 때, 폭발 범위 안에 있는 오브젝트들과 충돌체크를 한다.
  2. 그 오브젝트들 중 수류탄 피격 가능한 Tag를 가지고 있는 오브젝트들의 collider를 리스트에 저장한다.
  3. 리스트에 저장한 모든 collider에 raycast를 쏜다.
  4. raycast에 충돌한 오브젝트의 Tag가 수류탄 피격 가능한 Tag면 데미지를 입힌다.

그림판에서 대충 그린 그림으로 설명하면 수류탄이 터질 때 폭발 범위만큼 몬스터를 체크해서 해당 몬스터들에게 전부 레이캐스트를 쏜다. 레이캐스트에 피격당하면 몬스터의 앞에 장애물이 없다는 뜻이므로 데미지를 입힌다.

설명 이미지
빨간 원은 폭발범위, 빨간 선은 레이캐스트이다.

중간에 기획이 바뀌어서 수류탄이 미사일이 됐지만, 폭발 타이밍 빼곤 동일하기에 처음 생각한대로 스크립트를 작성했다.

using System.Collections.Generic;
using UnityEngine;

public class Grenade : MonoBehaviour
{
    public float explosionRange;

    public GameObject explosionParticle;

    private GameObject curParticle;

    private void Explosion()
    {
        curParticle = Instantiate(explosionParticle, transform.position, transform.rotation);

        Collider[] colliders = Physics.OverlapSphere(transform.position, explosionRange);

        List<Collider> enemyColliders = new List<Collider>();

        foreach (var col in colliders)
        {
            if (col.CompareTag("Grenade_Target"))
            {
                enemyColliders.Add(col);
            }
        }

        foreach (var enemy in enemyColliders)
        {
            Vector3 direction = (enemy.transform.position - transform.position).normalized;

            RaycastHit hit;

            Debug.DrawRay(transform.position, direction * explosionRange, Color.red, 1f);

            if (Physics.Raycast(transform.position, direction, out hit, explosionRange))
            {
                if (hit.collider.gameObject.CompareTag("Grenade_Target"))
                {
                    Debug.Log(hit.collider.name + " 피격");
                }
            }
        }

        gameObject.SetActive(false);
        Invoke("DelayDestroy", 3f);
    }

    private void DelayDestroy()
    {
        Destroy(curParticle);
        Destroy(this.gameObject);
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, explosionRange);
    }

    private void OnCollisionEnter(Collision collision)
    {
        Explosion();
    }
}

0개의 댓글