-
DNF 충돌 시스템게임 클라이언트 개발/MakeDNF 2023. 12. 3. 19:22
Hitbox를 Collider Component를 사용하지 않고 직접 구현함에 따라 Unity의 충돌 시스템이 아닌 직접 충돌 알고리즘을 작성해야 한다.
던전 앤 파이터의 월드 좌표계는 회전할 일이 없다. (차원회랑의 모로스 보스의 패턴 중 장례식 패턴에서 화면이 회전하는 경우가 존재하나 이는 카메라 회전을 통해 구현할 수 있다.)
그렇다면 선택할 수 있는 충돌 알고리즘은 AABB 알고리즘과 OBB 알고리즘이 있다. 어떤 충돌 알고리즘을 사용할 지 선택하기 위해 오브젝트의 좌표계가 회전하는지에 대한 여부를 확인할 필요가 있다.
대표적인 회전된 오브젝트로 런처의 양자라는 스킬이 존재한다. 양자 스킬을 사용할 경우 대각선 방향으로 미사일 오브젝트가 떨어지며 미사일 오브젝트는 45도 회전되어있다.
미사일 오브젝트의 히트박스가 회전되있을 경우 첫번째 애쉬코어와는 충돌이 발생하지 않아야 한다.
하지만 첫번째 애쉬코어와 충돌함을 확인할 수 있다. 즉, 미사일 그래픽이 회전되있더라도 히트박스는 회전시키지 않았고, OBB 알고리즘이 아닌 AABB 알고리즘을 사용했음을 추측할 수 있다.
$XZ$ 평면에서의 충돌 시 Hitbox 모양은 Box와 Circle 총 두 가지가 있고, $XY$ 평면에서의 충돌 시 Hitbox 모양은 Box로 통일했다. 이에 따라 AABB 알고리즘을 작성했다.
Box, Box
Box와 Box의 충돌 검사 로직은 두 Box의 각 축의 최대, 최소값을 비교하면 된다. Box의 하나의 축이라도 1번 Box의 최소값이 2번 Box의 최대값보다 크거나 1번 Box의 최대값이 2번 Box의 최소값보다 작다면, 충돌하지 않음을 의미한다.
bool CheckBB(Hitbox b1, Hitbox b2) // collision do not occur in X axis if b1.maxX < b2.minX or b1.minX > b2.maxX return false // collision do not occur in Z axis if b1.maxZ < b2.minZ or b1.minZ > b2.maxZ return false return true // collision occur in XZ coordinates
Circle, Circle
Circle과 Circle의 충돌 검사 로직은 두 Circle의 중점 간 거리와 각 Circle의 반지름의 합을 비교하면 된다. 반지름의 합이 두 Circle의 중점 간 거리보다 작다면, 충돌하지 않음을 의미한다.
bool CheckCC(Hitbox c1, Hitbox c2) dist = (c1.center - c2.center).sqrMagnitude sumRadius = c1.radius + c2.radius // collision do not occur if dist > sumRadius return false return true // collision occur
Box, Circle
Box와 Circle의 충돌 검사 로직은 Box를 기준으로 영역을 나누어 Circle의 중점의 위치에 따라 Box와 비교하면 된다.
- 4 : Box와 Circle은 충돌함
- 1, 7 : Circle과 Box 중점의 $Y$축 거리를 Circle의 반지름과 Box의 높이의 절반의 합과 비교한다.
- 3, 5 : Circle과 Box 중점의 $X$축 거리를 Circle의 반지름과 Box의 넓이의 절반의 합과 비교한다.
- 0, 2, 6, 8 : Box의 각 모서리가 Circle의 내부에 위치하는지 확인한다.
bool CheckBC(Hitbox b, Hitbox c) column = b.maxX < c.center.x ? 2 : (b.minX > c.center.x ? 0 : 1) row = b.maxY < c.center.y ? 2 : (b.minY > c.center.y ? 0 : 1) index = column + 3 * row if index = 4 return true // collision occur elif index = 1, 7 return Abs(b.center.y, c.center.y) < b.height * 0.5f + c.radius elif index = 3, 5 return Abs(b.center.x, c.center.x) < b.width * 0.5f + c.radius return CheckInsideCircle(c, b.corner)
'게임 클라이언트 개발 > MakeDNF' 카테고리의 다른 글
Skill 시스템 구현 및 개선 (0) 2024.01.10 DNF Input System (0) 2023.12.11 Hitbox with DNFTransform (0) 2023.12.02 2.5D 좌표계, DNFTransform (0) 2023.12.01 프로젝트를 시작하기 전에 (0) 2023.11.29