
처음에 유닛 충돌 처리를 CharacterBody2D의 CollisionShape2D 하나로 다 했다. 이동 충돌이랑 피격 판정이 같은 도형에 섞여 있으니까 뭔가 이상한 일이 계속 생겼다. 공격 범위가 이동 충돌과 간섭하거나, 팀 구분 없이 아군끼리도 피격 처리되는 식이었다.
역할을 나눴다
정리를 해보니 충돌에는 두 가지가 있었다. 이동할 때 벽이나 지형과 막혀야 하는 물리 충돌, 그리고 공격이 닿았을 때 데미지를 받는 피격 판정. 이걸 분리하기로 했다.
CollisionShape2D는 이동 전용으로만 남겼다. 피격 판정은 Hurtbox라는 Area2D를 따로 만들고, 공격 판정은 Hitbox라는 Area2D를 따로 만들었다. Hurtbox는 “나를 때릴 수 있는 영역”이고, Hitbox는 “내가 때리는 영역”이다.
팀 기반 레이어 설정
Area2D를 분리해도 아군끼리 피격되는 문제가 남았다. 이걸 해결한 게 collision layer/mask 동적 설정이다.
Godot에서는 Physics Layer를 비트마스크로 관리한다. ALLY 팀은 레이어 1, ENEMY 팀은 레이어 2로 정했다. Hurtbox는 자기 팀 레이어에 올리고, Hitbox는 상대 팀 레이어만 감지하도록 설정했다. 유닛이 생성될 때 team 값에 따라 동적으로 layer와 mask를 설정해주면 된다.
이렇게 하니까 코드에서 “상대방인지 확인” 같은 조건 없이도 Hitbox.body_entered 시그널이 항상 적군만 감지했다.
화살 관통도 자연스럽게
이 구조에서 화살 관통(pierce_count) 처리도 깔끔해졌다. Projectile에도 Hitbox를 붙이고 같은 레이어 규칙을 적용했다. 충돌할 때마다 pierce_count를 줄이고, 0이 되면 제거한다. Hurtbox/Hitbox 분리가 되어 있으니까 발사체도 같은 팀 충돌 규칙을 그대로 재사용했다.
정리하자면
이동 충돌과 피격 판정을 같은 Shape으로 처리하면 책임이 섞여서 나중에 고치기 어려워진다. Hurtbox/Hitbox로 분리하고 팀 기반 레이어를 설정하는 게 처음엔 번거로워 보여도, 이후 모든 전투 관련 기능을 훨씬 단순하게 만들어준다.








