충돌 회피 프로세스
경로 따르기 중 동적 회피는 다음 요구 사항을 충족하기 위해 각 프레임에서 속도를 계산하는 프로세스입니다.
- 경로에서 이동 중인 봇이나 정적 봇 또는 장애물을 피합니다.
- 계산된 경로를 따르는 속도를 선택합니다(너무 멀리 빗나가지 않음).
- NavMesh 경계 및 계산된 채널을 반영합니다.
- 가능한 안정된 상태에 있는 동안에는 회피 노력을 최소화합니다.
동적 회피는 다음 단계로 구성됩니다.
- 잠재적 충돌체를 수집합니다. 충돌체 수집을 참조하십시오.
- 다양한 조건에서 회피 속도 세트를 생성하고 점수화합니다. 회피 속도 생성을 참조하십시오.
- 지정된 프레임에 적용하는 데 가장 적합한 속도를 선택합니다. 최종 점수를 위한 유틸리티 함수를 참조하십시오.
다음 섹션에서는 동적 회피 프로세스에 대해 설명합니다.
충돌체 수집
장면의 전체 월드 요소에 따라 봇에 대한 회피를 계산하는 것은 비용이 많이 듭니다. 또한 회피는 대부분 로컬이고 근처의 엔티티에 따라 달라지기 때문에
목적에 맞게 사용할 수 없습니다.
또한 지정된 프레임에서 피하려는 엔티티가 시간 일관성으로 인해 후속 프레임에서 거의 같을 수 있습니다. 따라서 NavMesh 전파 구조를 이용하면
근처의 잠재적 충돌체 목록을 구성할 수 있습니다. 지정된 프레임 속도로 이 목록을 업데이트해야만 합니다. 다음 그림은 피할 수 있는 엔티티를 표시하는
충돌체 수집 범위를 보여줍니다.
ColliderCollectorConfig에서 이 프로세스를 구성할 수 있습니다. 매개변수는 다음과 같습니다.
- m_colliderCollectorRadius – 잠재적 충돌체를 수집하는 봇 주위의 반지름을 미터 단위로 정의합니다.
- m_colliderCollectorHalfHeight – 잠재적 충돌체를 수집하는 봇 고도의 위와 아래 높이를 미터 단위로 정의합니다.
- m_colliderCollectorFramesBetweenUpdates – 잠재적 충돌체의 연속된 두 개의 수집 사이의 프레임 수를 정의합니다.
회피 속도 생성
지정된 시간에 있는 봇의 경우 엔티티가 다양한 범위의 잠재적 속도에 도달할 수 있습니다. 경로 따르기와 무질서한 동작을 방지하기 위해 회피 속도 세트를
고정된 범위로 제한할 수 있습니다.
먼저 전역 경로 따르기 방향을 결정해야 합니다. 경로 따르기 프로세스와 호환되도록 이 방향이 계산됩니다.
- 바로 가기 모드 – 경로에서 대상을 지원하는 현재 경로 가장자리의 방향을 사용합니다. 다음 그림은 회피의 참조 방향이 현재 경로 가장자리와 평행함을 보여줍니다.
- 채널 모드 – 현재 채널 섹션의 방향을 사용합니다. 다음 그림은 참조 방향이 현재 섹션의 두 게이트 사이의 방향에 평행함을 보여줍니다.
이제 경로 따르기 방향 주위로 N 회피 속도의 샘플을 생성합니다. 다음 그림은 생성된 속도 샘플을 보여주며 기본 점수는 모두 1.0입니다.
이러한 속도는 봇 구성에서 원하는 속도와 일치합니다. AvoidanceConfig에서 이러한 속도 샘플의 숫자와 각도 범위를 구성할 수 있습니다. 매개변수는 다음과 같습니다.
- m_avoidanceAngleSpan – 회피 속도에 대한 각도 범위(도)입니다.
- m_avoidanceSampleCount – 회피 속도에 대한 샘플 개수입니다.
이제 최상의 속도를 선택하기 위한 점수 프로세스를 수행할 수 있습니다.
충돌 시간
회피는 공간 및 시간에서 모두 로컬입니다. 수평선의 역할을 하는 시간 제한을 지정하고 각 샘플에 대해 수집한 충돌체를 사용하여 충돌 시간을 계산할
수 있습니다. 다음 그림은 지정된 프레임에 대해 계산된 충돌 시간을 보여줍니다.
충돌이 없거나 충돌이 구성된 시간 제한 이상인 경우 샘플 비용을 시간 제한으로 설정할 수 있습니다.
NavMesh/채널 경계
NavMesh/채널 경계의 거리에 따라 샘플을 점수화할 수 있습니다. 다음 그림은 NavMesh 외부로 나가는 샘플이 잘못된 점수를 얻는 것을 보여줍니다.
충돌 비율에 대한 시간
충돌 시간을 수평선으로 나누어 0.0에서 1.0f 사이의 비율을 계산할 수 있습니다. 여기서 1.0f는 가장 안전한 속도입니다. 다음 그림은 충돌
시간을 비율로 보여줍니다.
AvoidanceConfig에서 시간 수평선을 지정할 수 있습니다. 매개변수는 다음과 같습니다.
- m_minimalTimeToCollision – 장애물이 N초 미만에 다른 장애물과 충돌하는 경우 회피를 위해 이를 고려합니다.
- m_safetyDistance – 너무 가깝게 이동하는 것을 피하기 위한 충돌체 주위의 안전 거리입니다. 충돌체에서 떨어져 있도록 유지하는 속도를 선택하기 위해 안전한 거리만큼
충돌체의 크기를 약간 확장할 수 있습니다.
스무딩
샘플링은 단지 몇 도로 유효한 샘플과 잘못된 샘플을 구별하기 때문에 정확하지 않을 수 있습니다. 안전하지 않은 샘플을 선택하는 것을 방지하기 위해
인접한 샘플을 사용하여 각 속도 샘플에 대한 평균 충돌 시간 비율을 계산할 수 있습니다. 다음 그림은 스무딩 충돌 시간을 보여줍니다.
이제 충돌이 없는 안전한 속도를 선택할 수 있습니다. 그러나 여러 가지 가능성이 있으므로 다른 두 조건을 고려하여 결정할 수 있습니다.
원하는 속도
경로 따르기가 이미 원하는 속도를 생성했습니다. 이 속도를 이용하면 이 속도를 기준으로 멀리 떨어져 있는 정도에 따라 샘플을 점수화할 수 있습니다.
다음 그림은 멀리 떨어져 있는 정도에 따라 샘플을 점수화하기 위해 원하는 속도(녹색)를 사용하는 방법을 보여줍니다.
이전 속도
안정성을 더 높이기 위해 이전에 계산한 속도를 기준으로 유사한 계산을 수행할 수 있습니다. 다음 그림은 이전 속도(빨간색)에 따라 점수화하는 방법을
보여줍니다.
최종 점수를 위한 유틸리티 함수
각 샘플에 대해 다음 유틸리티 함수를 사용하여 최종 점수를 계산할 수 있습니다.
Final Score = (A * CollisionTimeRatio) + (B * DesiredVelocityDistance) + (C * PreviousVelocityDistance)
여기서 A, B, C는 사용자가 구성할 수 있는 상수입니다(A + B + C = 1.0인 경우 가장 적합함). 최종 점수를 가져온 다음 샘플의 점수가
가장 높은 속도를 반환합니다. 다음 그림은 회피에 대해 출력하기 위해 선택한 최종 점수 및 최종 속도를 보여줍니다.
AvoidanceConfig에서 A, B 및 C를 구성할 수 있습니다. 매개변수는 다음과 같습니다.
- m_timeToCollisionInfluence – 회피 속도 선택 시 충돌에 대한 시간의 영향입니다.
- m_desiredVelocityInfluence – 회피 속도 선택 시 원하는 속도의 영향입니다.
- m_previousVelocityInfluence – 회피 속도 선택 시 이전 속도의 영향입니다.
중지
좋은 회피 솔루션이 없는 경우 다음 충돌 시간이 지정된 임계값 미만인 경우 엔티티가 중지하도록 0의 속도를 반환할 수 있습니다. 매개변수는 다음과
같습니다.
- m_stopCollisionTime – stopCollisionTime초 미만에서 충돌을 피할 수 없는 경우 엔티티가 중지됩니다. 중지된 다음 불규칙한 이동을 방지하기 위해 잠시 동안 이 결정을 커밋하는 것이 좋습니다.
- m_stopWaitTime – 엔티티가 중지되면 stopWaitTime초를 기다렸다가 다시 이동합니다.
일부 경우 먼저 속도를 늦추거나 엔티티가 중지하는 기능을 비활성화할 수 있습니다. 매개변수는 다음과 같습니다.
- m_enableSlowingDown – true로 설정되면 줄어든 속도를 사용하는 속도 후보를 고려합니다. 그렇지 않으면 Bot::GetDesiredSpeed() 길이를 사용하는 속도 후보만 고려합니다.
- m_enableStop – true로 설정되면 null 속도 후보를 고려합니다. 그렇지 않으면 AvoidanceSolver에서 봇의 중지를 고려하지 않기 때문에 이로 인해 때로는 충돌체를 강제로 통과합니다.
너무 오랫동안 차단되는 경우에도 강제로 통과하고 싶을 수 있습니다. 매개변수는 다음과 같습니다.
- m_enableForcePassage – true로 설정되면 한동안 다른 솔루션을 찾지 못하는 경우 충돌에 대한 솔루션이 허용됩니다.
- m_waitPassageTimeLimit – m_enableForcePassage가 true로 설정되면 m_waitPassageTimeLimit초가 지연된 후에만 강제로 통과합니다.
- m_forcePassageTimeLimit – m_enableForcePassage가 true로 설정되면 통과는 m_waitPassageTimeLimit초가 지연된 후에만 기껏해야 m_forcePassageTimeLimit초 동안 강제로 통과합니다.