타격 판정 기획: 스킬 영역(AoE) 레이캐스트 히트박스와 피격박스의 명확한 판정 분리
공격 영역과 피해 수신 영역을 구분하고 광역 스킬의 거리·각도·장애물 검사를 연결하는 설계안을 다룹니다. Unity 예제의 중심점 판정과 트리거·레이캐스트 전제도 설명합니다.

히트박스(Hitbox)와 피격박스(Hurtbox)의 역할 분리
이 글은 공격 영역과 피해 수신 영역을 분리해 검사하는 설계안을 제안합니다. 같은 콜라이더를 여러 목적으로 사용한다면 크기 변경의 영향과 공격자·아군 필터를 확인해야 합니다. 하나의 콜라이더를 쓴다는 이유만으로 자가 피격이 발생하는 것은 아니며 역할 분리만으로 공정성이나 성능이 보장되지도 않습니다.
여기서는 히트박스(Hitbox)를 공격 영역, 피격박스(Hurtbox)를 피해 수신 영역으로 정의하고 필요한 충돌·쿼리 대상을 각각 설정합니다. 두 영역은 박스 외의 도형이나 수식으로도 표현할 수 있습니다.
- 히트박스 (Hitbox): 무기 끝, 투사체, 스킬 효과 범위 등 공격 주체가 데미지를 주기 위해 특정 순간에 생성하는 영역입니다.
- 피격박스 (Hurtbox): 캐릭터의 피격 가능 부위를 감싸고 있으며 상시 또는 무적 상태를 제외한 프레임 동안 활성화되는 피해 수신 영역입니다.
Unity의 Layer Collision Matrix는 레이어 간 충돌 대상을 설정합니다. OverlapSphere나 Raycast로 직접 조회하는 예제에서는 각 호출의 layerMask와 QueryTriggerInteraction도 설정해야 합니다. 피격박스 조회와 장애물 조회를 나누고 공격자·아군 제외 규칙은 별도로 구현합니다. 연산 비용은 대상 수와 호출 횟수를 측정해 판단합니다.

광역 스킬(AoE)의 범위 판정 수식
아래 예제는 발동 시점의 위치를 검사합니다. 물리 Overlap과 수식 검사 모두 한 시점만 조회하면 두 조회 사이에 영역을 통과한 대상을 놓칠 수 있으므로 이 조합만으로 빠른 이동의 누락이 해결되지는 않습니다. 이동 경로 검사나 추가 샘플링이 필요한지는 스킬의 판정 규칙에 따라 정합니다.
이 예제는 3D 공간에서 거리로 자른 원뿔 방향 영역을 검사하며 각 피격박스의 중심점을 대표점으로 사용합니다. 은 발동 위치, 은 대표점, 는 정면 단위 벡터, 은 반경, 는 전체 벌어짐 각도입니다. 코드는 각도를 도 단위로 받습니다. 평면 부채꼴이 목적이라면 수평면 투영과 별도의 높이 허용 범위를 정의해야 합니다.
대표점과 발동점의 거리가 양수일 때 단위 벡터 를 구합니다. 두 단위 벡터의 내적은 사잇각의 코사인이므로 반각 이내인지 다음처럼 검사합니다.
이 두 조건은 피격박스 전체와 영역의 교차 검사가 아니라 대표점의 포함 검사입니다. 코드의 Collider.bounds.center는 월드 공간 경계 볼륨의 중심이며 실제 도형의 무게중심을 뜻하지 않습니다. 큰 피격박스의 일부만 범위에 들어온 경우를 타격할지는 별도 정책으로 정해야 합니다. 아래 코드는 거리 0.001 이하의 대표점과 길이 0.00001 이하의 정면 벡터를 제외하는 예시입니다. 이 허용 오차와 근거리 처리는 프로젝트의 좌표 단위와 게임 규칙에 맞춰 조정합니다.
장애물 차단을 고려한 레이캐스트(Raycast) 보완
거리·각도 검사와 피격박스 Overlap만으로 장애물 차단 여부를 판단하지는 않습니다. 벽에 막히는 스킬이라면 후보 대표점까지 레이캐스트를 추가할 수 있습니다. 벽을 통과하는 스킬은 다른 정책을 사용할 수 있으며 단일 중심점 레이는 대상의 일부가 노출된 상황을 완전히 표현하지 못합니다.
graph TD
A[스킬 발동 시점] --> B[AoE 영역 내 Hurtbox 탐색]
B --> C{Target Hurtbox 존재?}
C -- 없음 --> D[판정 종료]
C -- 있음 --> E[발동 위치에서 Hurtbox 중심으로 Raycast 발사]
E --> F{중간 장애물 차단 여부?}
F -- 장애물 있음 --> G[타격 무효 처리 Occluded]
F -- 장애물 없음 --> H[데미지 및 상태 변화 적용]
1차 검출된 피격박스의 중심점 혹은 주요 피벗 위치를 향해 레이캐스트를 발사했을 때 피격박스에 도달하기 전 엄폐물(Obstacle) 레이어와 먼저 충돌한다면 해당 타격은 무효 처리됩니다.

두 이미지는 판정 정책을 설명하는 개념도이며 실제 Unity 물리 쿼리의 실행 결과를 기록한 자료는 아닙니다.
실전 구현을 위한 C# 코드 구조
Unity 2022.3의 OverlapSphere와 Raycast를 사용하는 함수 예시입니다. Overlap은 구와 닿거나 구 안에 있는 콜라이더를 반환하므로 중심점의 거리도 다시 검사합니다. 피격박스는 트리거를 포함하고 장애물은 비트리거 콜라이더라고 가정합니다. 레이 시작점이 장애물 콜라이더 내부면 Raycast가 그 콜라이더를 감지하지 못하므로 발동점의 유효 위치는 별도로 확인합니다.
using UnityEngine;
using System.Collections.Generic;
public class SkillHitboxEvaluator : MonoBehaviour
{
[SerializeField] private LayerMask hurtboxLayer;
[SerializeField] private LayerMask obstacleLayer;
public List<Collider> EvaluateConeAoE(Vector3 origin, Vector3 forward, float radius, float angleDegree)
{
List<Collider> validTargets = new List<Collider>();
bool IsFinite(float v) => !float.IsNaN(v) && !float.IsInfinity(v);
if (!IsFinite(origin.x) || !IsFinite(origin.y) || !IsFinite(origin.z)
|| !IsFinite(forward.x) || !IsFinite(forward.y) || !IsFinite(forward.z)
|| !IsFinite(radius) || radius <= 0f
|| !IsFinite(angleDegree) || angleDegree < 0f || angleDegree > 360f
|| !IsFinite(forward.sqrMagnitude) || forward.sqrMagnitude <= 1e-10f)
return validTargets;
forward /= forward.magnitude;
Collider[] overlapColliders = Physics.OverlapSphere(
origin, radius, hurtboxLayer, QueryTriggerInteraction.Collide);
float cosHalfAngle = Mathf.Cos((angleDegree * 0.5f) * Mathf.Deg2Rad);
foreach (var col in overlapColliders)
{
Vector3 targetPos = col.bounds.center;
Vector3 dirToTarget = (targetPos - origin);
float distance = dirToTarget.magnitude;
if (!IsFinite(distance) || distance <= 0.001f || distance > radius) continue;
dirToTarget /= distance;
// 1. 각도 검사
if (Vector3.Dot(forward, dirToTarget) >= cosHalfAngle)
{
// 2. 레이캐스트 장애물 검사
if (!Physics.Raycast(origin, dirToTarget, distance,
obstacleLayer, QueryTriggerInteraction.Ignore))
{
validTargets.Add(col);
}
}
}
return validTargets;
}
}
반환값은 콜라이더 목록입니다. 같은 캐릭터가 여러 피격박스를 가지면 피해 적용 전에 캐릭터 ID로 중복을 제거하고 공격자·아군을 제외합니다. 이 예제는 배열과 목록을 할당하므로 호출 빈도와 대상 수에 따른 비용도 측정해야 합니다.
정리
공격·피해 수신·장애물의 역할을 정하고 중심점 포함 여부와 실제 도형 교차, 근거리 예외, 엄폐 정책을 구분해 구현합니다. 큰 대상의 부분 노출과 빠른 이동, 여러 피격박스, 공격자 제외를 테스트해 의도한 타격 규칙과 결과가 일치하는지 확인합니다.



