유니티에서 몬스터의 공격 판정을 위해 자식 오브젝트로 트리거 콜라이더(Hitbox)를 추가했을 때, 플레이어가 해당 영역에 물리적으로 밀리거나 접근하지 못하는 현상이 발생할 수 있습니다. 오늘 해결한 사례를 바탕으로 그 원인과 최적의 해결책을 정리합니다.
1. 문제 현상
- 상황: 몬스터(부모)에게 Rigidbody가 있고, 무기(자식)에
isTrigger가 켜진 박스 콜라이더가 있음. - 증상: 몬스터가 공격 중이 아님에도 플레이어가 몬스터 근처(무기 콜라이더 영역)에 가려고 하면 ‘투명한 벽’에 막힌 것처럼 밀려남.
- 의문: 트리거(
isTrigger)는 물리적 충돌을 일으키지 않아야 하는데 왜CharacterController는 이를 벽으로 인식하는가?
2. 원인 분석: 복합 콜라이더(Compound Collider)와 소유권
유니티 물리 엔진(PhysX)은 부모에게 Rigidbody가 있고 자식에게 Colliders가 있는 경우 이를 하나의 단일 물리 유닛(Actor)으로 취급합니다.
핵심 매커니즘:
- 메시지 통합: 자식 콜라이더에서 발생하는 모든 충돌 이벤트(
OnTriggerEnter등)는 Rigidbody가 있는 부모 오브젝트로 전달됩니다. - 레이어 간섭 (The Trap): 유니티의
CharacterController는 물리 연산 시 “이 Actor(Rigidbody)와 내가 부딪혀야 하는가?”를 먼저 판단합니다. - 만약 부모(Rigidbody)의 레이어가 플레이어와 충돌하도록 설정되어 있다면, 물리 엔진은 그 리지드바디에 속한 모든 콜라이더(자식 트리거 포함) 영역을 “안전을 위해 진입을 막아야 할 물리적 공간”으로 과하게 인식해 버립니다.
3. 해결 전략 (Action Plan)
단계 1: 레이어 충돌 매트릭스 최적화 (가장 중요)
액션 게임(하데스 스타일)에서는 캐릭터 본체끼리 밀어내는 물리력을 제거하는 것이 조작감 면에서 유리합니다.
- 설정:
Project Settings > Physics > Layer Collision Matrix - 조치:
Player레이어와Monster(본체) 레이어 간의 충돌 체크를 해제합니다. - 결과: 부모의 “물리적 차단막”이 사라지면서, 자식인
Monster Weapon레이어의 트리거가 본래 의도대로(벽이 아닌 감지 영역으로) 작동하게 됩니다.
단계 2: 히트박스 활성화 제어 (성능 및 정확도)
공격 중이 아닐 때는 물리 엔진이 아예 해당 콜라이더를 무시하도록 코드로 제어합니다.
- 방법:
_isActive플래그만 사용하는 대신,Collider.enabled = false를 직접 사용합니다. - 장점: 물리 엔진의 공간 쿼리 목록에서 완전히 제외되어 불필요한 연산을 줄이고
CharacterController와의 간섭을 원천 차단합니다.
단계 3: 무기 리지드바디 설정
자식 오브젝트(무기)에 리지드바디가 꼭 필요하다면 반드시 Is Kinematic = true로 설정해야 합니다. Non-Kinematic 리지드바디는 트리거일지라도 물리적 반발력을 발생시킬 확률이 높습니다.
4. 최종 결과 코드 예시 (Hitbox.cs)
public void Activate(DamageData data)
{
_currentDamageData = data;
_hitTargets.Clear();
_isActive = true;
if (_collider) _collider.enabled = true; // 물리 엔진에 등록
}
public void Deactivate()
{
_isActive = false;
_hitTargets.Clear();
if (_collider) _collider.enabled = false; // 물리 엔진에서 제거
}
요약
“부모 리지드바디의 레이어가 자식 콜라이더의 물리적 성질을 결정한다.” 플레이어를 밀어내지 않으면서 트리거 판정만 남기고 싶다면, 부모 레이어의 충돌 체크를 끄고 자식 레이어의 트리거만 활용하십시오.