본문 바로가기
개발/Unity

(Unity) 근처 적을 스캔하고 최단 거리 대상 찾기

by DinoDev 2025. 12. 13.
728x90
반응형

게임 개발을 하다 보면, 캐릭터가 주변의 적이나 아이템을 자동으로 감지하고 그중에서 가장 가까운 대상을 선택해야 하는 경우가 정말 많습니다.

유니티 2D 환경에서 Physics2D.CircleCastAll을 활용하여 주변 목표물을 효과적으로 스캔하고, 가장 가까운 대상을 정확하게 찾아내는 방법에 대한 스크립트를 공유하고 분석해 보겠습니다.

📝 핵심 스캐너 스크립트 살펴보기

이 스크립트는 Scanner라는 이름으로 MonoBehaviour를 상속받으며, 주변을 원 형태로 스캔하는 역할을 합니다.

public class Scanner : MonoBehaviour
{
    public float scanRange;
    public LayerMask targetLayer;
    public RaycastHit2D[] detectedTargets;
    public Transform nearestTarget;
    // ... (메소드)
}

💡 변수 해설

  • scanRange: 우리가 주변을 탐색할 원의 반지름(반경)입니다. 인스펙터 창에서 쉽게 조절하며 탐색 범위를 시각적으로 확인할 수 있습니다.
  • targetLayer: 가장 중요한 설정입니다! 적이나 목표물 등 감지하고자 하는 대상이 속한 레이어를 지정합니다. 불필요한 오브젝트(배경, 벽 등)를 걸러내는 필터 역할을 합니다.
  • nearestTarget: 최종적으로 감지된 대상 중에서 가장 가까운 대상의 Transform이 여기에 저장됩니다.

🔍 스캔 작동 원리

CircleCastAll의 마법주변 감지는 물리 업데이트 주기인 FixedUpdate에서 실행됩니다. 이는 물리 관련 작업의 안정성을 높여줍니다.

void FixedUpdate()
{
    detectedTargets = Physics2D.CircleCastAll(
        transform.position, // 기준 위치 (나 자신)
        scanRange,          // 탐색 범위 (반지름)
        Vector2.zero,       // 방향 (고정된 원 형태이므로 zero)
        0f,                 // 거리 (고정된 원 형태이므로 0)
        targetLayer         // 탐색할 레이어 마스크
    );

    nearestTarget = FindNearestTarget();
}

Physics2D.CircleCastAll을 사용한 이유

이 메소드는 특정 지점(transform.position)에 반경 scanRange를 가진 원을 만들었을 때, 그 원 안에 겹치는 모든 2D 충돌체 정보를 배열(detectedTargets)로 반환합니다.

directiondistanceVector2.zero0f로 설정함으로써, 우리는 "현재 위치에 고정된 원 안에 무엇이 있나?"를 묻는 OverlapCircleAll과 거의 동일하게, 하지만 좀 더 유연하게 정보를 얻어낼 수 있습니다.


🥇 최단 거리 탐색 알고리즘

가장 가까운 적을 찾아서detectedTargets 배열에는 스캔 범위 내 모든 적의 정보가 담겨 있습니다.
이제 이 중에서 가장 가까운 단 하나의 대상을 골라내야 합니다.

Transform FindNearestTarget()
{
    float nearestDistance = Mathf.Infinity;
    Transform result = null;

    foreach (RaycastHit2D hit in detectedTargets)
    {
        // 1. 기준점과 현재 감지된 대상 간의 실제 거리 계산
        float distance = Vector2.Distance(transform.position, hit.transform.position);

        // 2. 현재 대상의 거리가 지금까지 발견한 '최단 거리'보다 짧은가?
        if (distance < nearestDistance)
        {
            // 3. 더 가까운 대상을 찾았으므로 값 업데이트
            nearestDistance = distance;
            result = hit.transform;
        }
    }
    return result; // 가장 가까운 대상의 Transform 반환
}
  1. 우선, nearestDistanceMathf.Infinity (무한대)로 초기화합니다. 이렇게 하면 배열의 첫 번째 대상과의 거리가 무조건 최단 거리가 됩니다.
  2. detectedTargets 배열을 foreach 루프로 돌며 모든 대상을 확인합니다.
  3. Vector2.Distance를 이용해 실제 거리를 계산하고, 현재 기록된 nearestDistance와 비교하여 가장 작은 값을 계속 갱신합니다.

최종적으로 루프가 끝났을 때, result에 저장된 Transform이 바로 우리 캐릭터와 가장 가까운 대상이 되는 것입니다!

728x90
반응형