충돌 엔진은 어떻게 작동합니까?


78

충돌 엔진 은 정확히 어떻게 작동합니까?

이것은 매우 광범위한 질문입니다. 어떤 코드가 서로에게 튀는 것을 유지합니까? 플레이어가 벽을 통과하는 대신 벽으로 들어가는 코드는 무엇입니까? 코드는 중력과 충돌이 정상적으로 작동하도록 플레이어의 위치와 물체의 위치를 ​​지속적으로 새로 고치는 방법은 무엇입니까?

충돌 엔진이 무엇인지 모르는 경우 기본적으로 플랫폼 게임 에서 플레이어가 벽 등을 치도록하는 데 일반적으로 사용됩니다 . 2D 유형과 3D 유형이 있지만 모두 충돌을 일으 킵니다.

그렇다면 충돌 엔진이 계속 작동하는 이유는 무엇입니까?


3
경계 상자와 구로 속임수를 쓸 수 있습니다. 그런 다음 더 자세히 검사 할 수 있습니다. cs.unc.edu/~dm/collision.html en.wikipedia.org/wiki/Collision_detection은 항상 순진 알고리즘으로 천천히이 작업을 수행 할 수 있습니다. Comp Geometry에는 문제의 기하학적 특성을 활용하고 알고리즘을 더 빠르게 만드는 몇 가지 트릭이 있습니다. 여기에 아주 좋은 논문은 다음과 같습니다 cs.hku.hk/research/techreps/document/TR-2005-01.pdf

무엇 충돌 엔진은 ?

4
@gnat 충돌 엔진은 기본적으로 게임 (일반적으로)에서 사용되는 엔진이므로 플레이어가 밥을 벽으로 움직일 때마다 밥이 멈추고 밥이 벽을 통과하지 않습니다. 또한 일반적으로 게임에서 중력을 처리하고 이와 같은 환경적인 것들을 처리합니다.
JXPheonix

답변:


172

충돌 엔진과 물리 엔진 사이에는 큰 차이가 있습니다. 물리 엔진은 일반적으로 충돌 엔진을 사용하지만 동일한 작업을 수행하지는 않습니다.

충돌 엔진은 충돌 감지와 충돌 응답의 두 부분으로 나뉩니다. 후자는 일반적으로 물리 엔진의 일부입니다. 이것이 충돌 엔진과 물리 엔진이 일반적으로 동일한 라이브러리에 롤링되는 이유입니다.

충돌 감지는 이산 형과 연속 형의 두 가지 형태로 제공됩니다. 고급 엔진은 서로 다른 속성을 갖기 때문에 두 가지를 모두 지원합니다. 일반적으로 연속 충돌 감지는 비용이 많이 들고 실제로 필요한 경우에만 사용됩니다. 충돌과 물리의 대부분은 이산 방법을 사용하여 처리됩니다. 불연속적인 방법으로, 물체는 서로 관통하게되고 물리 엔진은 물체를 밀어 내려합니다. 따라서 엔진은 실제로 플레이어가 벽이나 바닥을 부분적으로 걷는 것을 막지 않으며 플레이어가 부분적으로 벽 / 바닥에 있음을 감지 한 후에 엔진을 수정합니다. 여기서는 불연속 충돌 감지에 중점을 두겠습니다. 처음부터 구현 한 경험이 가장 많기 때문입니다.

충돌 감지

충돌 감지는 비교적 쉽습니다. 모든 객체에는 변형과 모양이 있습니다 (여러 개의 모양이있을 수 있음). 순진한 접근법은 충돌 엔진이 모든 객체 쌍을 통해 O (n ^ 2) 루프를 수행하고 쌍 사이에 겹침이 있는지 테스트합니다. 더 스마트 한 접근법에서, 다수의 공간 데이터 구조 (예를 들어, 정적 대 동적 객체에 대한), 각각의 객체에 대한 경계 형상, 및 각 객체에 대한 다중 부분 볼록한 서브 셰이프가 존재한다.

공간 데이터 구조에는 KD-Trees, Dynamic AABB 트리, Octrees / Quadtrees, Binary Space Partitioning 트리 등이 포함됩니다. 각각의 장단점이 있기 때문에 일부 고급 엔진은 둘 이상의 엔진을 사용합니다. 예를 들어 다이내믹 AABB 트리는 실제로 움직이는 객체를 다룰 때 정말 빠르고 훌륭합니다. KD- 트리는 객체가 충돌하는 정적 레벨 형상에 더 적합 할 수 있습니다. 다른 옵션도 있습니다.

광범위한 단계는 공간 데이터 구조와 각 객체에 대한 추상 경계 볼륨을 사용합니다. 경계 체적은 전체 물체를 둘러싸는 단순한 모양으로, 일반적으로 충돌 테스트를 저렴하게 유지하면서 가능한 한 "밀하게"둘러싸는 것을 목표로합니다. 가장 일반적인 경계 모양은 축 정렬 경계 상자, 개체 정렬 경계 상자, 구 및 캡슐입니다. AABB는 일반적으로 가장 빠르고 가장 쉬운 것으로 간주됩니다 (구면이 더 쉽고 빠르지 만 이러한 공간 데이터 구조의 대부분은 구를 AABB로 변환해야 함). 그러나 많은 객체에 적합하지 않은 경향이 있습니다. 캡슐은 캐릭터 수준 충돌을 처리하기 위해 3D 엔진에서 널리 사용됩니다. 일부 엔진은 두 가지 경계 모양을 사용합니다.

충돌 감지의 마지막 단계는 형상이 교차하는 위치를 정확하게 감지하는 것입니다. 이것은 항상 메쉬 (또는 2D의 다각형)를 사용하는 것을 의미하지만 항상 그런 것은 아닙니다. 이 단계의 목적은 미세한 수준의 디테일이 필요한 경우 (예 : 간신히 놓친 샷을 무시할 수있는 사수의 총알 충돌) 객체가 실제로 충돌하는지 확인하는 것입니다. 또한 물체가 충돌하는 위치를 정확히 찾아서 물체의 반응에 영향을줍니다. 예를 들어 상자가 테이블의 가장자리에 있으면 엔진이 테이블이 상자를 밀고있는 지점을 알아야합니다. 상자가 얼마나 멀리 매달려 있는지에 따라 상자가 기울어지고 떨어질 수 있습니다.

매니 폴드 생성에 문의

여기에 사용 된 알고리즘에는 널리 사용되는 GJK 및 Minkowski Portal Refinement 알고리즘과 Separating Axis 테스트가 포함됩니다. 널리 사용되는 알고리즘은 일반적으로 볼록한 모양에만 작동하므로 많은 복잡한 객체를 볼록한 하위 객체로 나누고 각각에 대해 충돌 테스트를 수행해야합니다. 이것이 단순화 된 메쉬가 충돌에 자주 사용되는 이유 중 하나이며, 적은 수의 삼각형을 사용하는 처리 시간이 단축됩니다.

이러한 알고리즘 중 일부는 객체가 확실히 충돌 한 것이 아니라 충돌 한 위치, 즉 서로 얼마나 멀리 침투하고 있으며 "접촉점"이 무엇인지 알려줍니다. 일부 알고리즘에는이 정보를 얻기 위해 다각형 클리핑과 같은 추가 단계가 필요합니다.

신체적 반응

이 시점에서 접촉이 발견되었으며 물리 엔진이 접촉을 처리하기에 충분한 정보가 있습니다. 물리 처리는 매우 복잡 할 수 있습니다. 간단한 알고리즘은 일부 게임에서 작동하지만 상자 스택을 안정적으로 유지하는 것은 매우 어렵고 많은 작업과 명백하지 않은 해킹이 필요합니다.

가장 기본적인 수준에서 물리 엔진은 다음과 같은 작업을 수행합니다. 충돌하는 객체와 접촉 매니 폴드를 가져오고 충돌 된 객체를 분리하는 데 필요한 새로운 위치를 계산합니다. 객체를이 새로운 위치로 옮길 것입니다. 또한이 푸시로 인한 속도 변화와 복원 (튀김) 및 마찰 값을 결합하여 계산합니다. 물리 엔진은 중력과 같은 물체에 작용하는 다른 힘을 적용하여 물체의 새로운 속도를 계산 한 다음 새로운 위치를 (다음 프레임) 적용합니다.

고급 물리 반응이 빠르게 복잡해집니다. 위의 접근 방식은 하나의 개체가 다른 두 개체 위에있는 것을 포함하여 많은 상황에서 세분화됩니다. 각 쌍을 자체적으로 처리하면 "지터"가 발생하고 개체가 많이 튀어 오릅니다. 가장 기본적인 기술은 충돌하는 객체 쌍에 대해 여러 가지 속도 수정 반복을 수행하는 것입니다. 예를 들어 상자 "A"가 두 개의 다른 상자 "B"와 "C"위에 놓이면 충돌 AB가 먼저 처리되어 상자 A가 상자 C로 더 기울어지게됩니다. 그런 다음 저녁에 AC 충돌이 처리됩니다. 상자를 약간 빼내고 A를 아래로 잡아 당겨 B로 넣으십시오. 그런 다음 또 다른 반복이 수행되므로 AC 수정으로 인한 AB 오류가 약간 해결되어 AC 응답에 약간 더 많은 오류가 발생합니다. AC가 다시 처리 될 때 처리됩니다. 반복 횟수는 고정되어 있지 않으며 "완벽한"시점이 아니라 의미있는 결과를 제공하는 반복 횟수에 관계없이 반복됩니다. 10 번의 반복이 전형적인 첫 시도이지만 특정 엔진과 특정 게임의 요구에 가장 적합한 수를 파악하려면 조정이 필요합니다.

연락 캐싱

많은 유형의 게임을 다룰 때 실제로 유용한 것으로 밝혀지는 다른 트릭이 있습니다. 연락처 캐싱은 더 유용한 것 중 하나입니다. 연락처 캐시를 사용하면 충돌하는 각 개체 집합이 조회 테이블에 저장됩니다. 충돌이 감지되면 각 프레임에서이 캐시를 쿼리하여 객체가 이전에 접촉했는지 확인합니다. 객체가 이전에 접촉하지 않은 경우 "새로운 충돌"이벤트가 생성 될 수 있습니다. 개체가 이전에 접촉 한 경우이 정보를 사용하여보다 안정적인 응답을 제공 할 수 있습니다. 프레임에서 업데이트되지 않은 컨택 캐시의 항목은 분리 된 두 개의 오브젝트를 나타내며 "분리 오브젝트"이벤트가 생성 될 수 있습니다. 게임 로직은 종종 이러한 이벤트에 사용됩니다.

게임 로직이 새로운 충돌 이벤트에 응답하여 무시 된 것으로 플래그를 지정할 수도 있습니다. 이것은 뛰어 넘을 수는 있지만 플랫폼과 같이 플랫폼에서 공통적 인 일부 기능을 구현하는 데 실제로 유용합니다. 순진한 구현은 플랫폼-> 캐릭터 충돌 정상 (플레이어의 머리가 플랫폼의 바닥에 부딪쳤다는 것을 나타냄)이있는 충돌을 무시할 수 있지만 접촉 캐싱이 없으면 플레이어의 머리가 플랫폼을 통해 튀어 나와서 시작하면 중단됩니다. 넘어지다. 이 시점에서 접점 법선이 위로 향하게되어 플레이어가 플랫폼을 통해 팝업하지 않아야 할 수도 있습니다. 접촉 캐싱을 통해 엔진은 초기 충돌 법선을 안정적으로보고 플랫폼과 플레이어가 다시 분리 될 때까지 모든 추가 접촉 이벤트를 무시할 수 있습니다.

슬리핑

또 다른 유용한 기술은 객체가 상호 작용하지 않는 경우 "잠 들어있는"것으로 표시하는 것입니다. 수면 오브젝트는 물리 업데이트를받지 않고 다른 수면 오브젝트와 충돌하지 않으며 기본적으로 잠들지 않은 다른 오브젝트와 충돌 할 때까지 제자리에 고정되어 있습니다.

그 영향은 아무 것도하지 않고 거기에 앉아있는 모든 충돌 오브젝트 쌍이 처리 시간을 차지하지 않는다는 것입니다. 또한, 일정량의 작은 물리 보정이 없기 때문에 스택은 안정적입니다.

객체는 단일 프레임 이상의 속도가 거의 0 일 때 수면의 후보입니다. 이 0에 가까운 속도를 테스트하는 데 사용하는 엡실론은 아마도 스택 된 객체에 약간의 지터가 필요하고 객체의 전체 스택이 잠들기를 원하기 때문에 일반적인 부동 소수점 비교 엡실론보다 약간 높을 것입니다. "충분히 근접한"상태를 유지하십시오 임계 값은 물론 조정과 실험이 필요합니다.

제약

많은 물리 엔진의 마지막 주요 비트는 제약 솔버입니다. 이러한 시스템의 목적은 스프링, 모터, 휠 축, 시뮬레이션 된 소프트 바디, 천, 로프 및 체인, 때로는 유체 (유체가 완전히 다른 시스템으로 구현되는 경우도 있음)와 같은 것을 쉽게 구현하는 것입니다.

제약 조건 해결의 기본 사항조차도 수학을 매우 집중적으로 사용할 수 있으며이 주제에 대한 저의 전문 지식을 뛰어 넘습니다. 이 주제에 대한 자세한 설명은 랜디의 물리학관한 훌륭한 기사 시리즈를 확인하는 것이 좋습니다 .


최소 충돌 해결 수를 해결하려는 경우 복잡한 설정에서 높은 충돌 수를 허용하면 프레임 속도가 크게 감소한다는 점을 고려하여 가능한 한 낮은 수를 유지해야 할 필요성도 해결해야합니다. 그런 다음 반복 횟수에 대해 이야기 할 때 쌍당 또는 모든 충돌에 대한 반복 횟수였습니다.
gardian06

1
@ gardian06 : 빠르게 작성된 개요이므로 상당히 확장 될 수 있습니다. 예를 들어 객체 잠자기를 언급하는 것을 잊어 버렸습니다. 반복의 경우 모든 쌍의 컬렉션을 반복하고 상대적으로 많은 반복 횟수 (20+)로도 성능 문제를 발견 한 적이 없습니다 (다시 말하지만 객체 수면과 관련되어 있으므로 해결하기 위해 상대적으로 적은 수의 활성 충돌이 발생합니다) ).
Sean Middleditch 2013 년

1
환상적인 답변, +1. 이것을 읽으면 이러한 알고리즘을 구현하고 싶습니다.
Miles Rout

3

일반적인 문제 : 가능한 모든 객체 조합 중 교차 볼륨이 0이 아닌 것을 확인하십시오.

순진하고 일반적인 접근 방식은 간단합니다. 가능한 각 객체 쌍에 대해 교차 체적을 계산하십시오. 이것은 비교적 비싼 교차 연산이 필요하기 때문에 일반적으로 실용적이지 않습니다.

따라서 실제 구현은 종종 전문화되어 교차 검사를 피하거나 비용을 절감 할 수있는 특정 가정을 만듭니다. 공간 분할은 개체가 일반적으로 전체 볼륨에 비해 작고 O (n log n)에 대한 비교 횟수를 줄인다는 사실을 이용합니다. 축 정렬 경계 상자와 경계 구체는 물체가 특정 압축 가정에 따르는 한 저렴한 거친 교차 검사를 제공합니다. 등등.


2

내가 사용한 한 "충돌 엔진" 은 이해하기가 매우 쉽다고 느꼈다 .

기본적으로, API 메소드를 갖는 오브젝트의 종류가 제공 collidesWith되도록을

  1. 그 매개 변수는 충돌에 "적합한"다른 종류의 개체였습니다
  2. 충돌 발생 여부에 따라 true 또는 false를 반환했습니다.
  3. 객체의 모든 경계 사각형 이 충돌 이벤트를 트리거 할지 아니면 이 사각형 내에서 불투명 한 픽셀 만 트리거 할 것인지 선택할 수있는 옵션이있었습니다 (픽셀 수준 감지).

내 응용 프로그램에서 collidesWith충돌이 발생했는지 여부를 찾기 위해 주기적으로 호출 했습니다.

아주 간단하지 않습니까?


어쩌면 약간의 상상력이 필요한 유일한 것은 평평한 사각형이 충돌하는 물체의 형상을 시뮬레이션하기에 충분하지 않은 경우 일 것입니다. 이 경우 단순히 하나 대신 여러 개의 충돌 가능한 객체를 사용해야합니다.

일반적으로 단일 충돌 사각형이 필요한 것을 수행하지 않는 것을 발견하면 더 많은 사각형 하위 요소로 사물을 분해하여 결합 할 때 원하는 요소를 시뮬레이션 / 근사하는 방법을 발명합니다.

  • 최종 사용자는 장면 뒤에 얼마나 많은 객체가 있는지 신경 쓰지 않습니다. 예를 들어 뒷마당 울타리가있는 집처럼 최종 결과가 기대하는 한 행복합니다.

    http://i.stack.imgur.com/4Wn5B.jpg


2

나는 당신이 당신이 말하는 것에 약간 혼란스럽고 몇 가지 다른 것에 대해 이야기하고 있다고 생각합니다.

이 아이템이 X 위치에서 Y 위치로 이동되었다고 말할 수있는 능력은 물리학을 기반으로합니다 (이것은 이동 방법 및 이동 이유도 공격합니다)

충돌 감지에 사용되는 방법은 게임 구조에 따라 결정됩니다. 게임이 열린 세상이라면 공간 분할 (quad-tree [3D 용 oct-tree], BSP, 전통적인 그리드 또는 모든 방식의 구식 테스트 방식)을 고려해야합니다.

충돌 감지 시스템을 구현하는 가장 좋은 방법은 단계적으로 수행하는 것입니다.

  1. 모든 개체를 일반 경계 볼륨 / 모양에 배치 한 다음 테스트

  2. 1이 통과하면 절대 형상을 테스트 할 준비가 될 때까지 더 복잡한 볼륨 / 모양 반복으로 반복

  3. 절대 형상 테스트 2 단계를 반복하는 횟수는 모양의 복잡성과 해당 모양의 정확도에 따라 결정됩니다.

이 단계들 각각은 초기 단계이며, 갈수록 충돌을 제거 할 목적으로, 3 단계에서 실제로 만지는 경우에만 true를 반환해야합니다.

마지막 부분은 충돌 해결입니다. 충돌을 찾은 후 발생하는 상황을 결정하고 충돌이 실제로 발생한 것으로 판명되었습니다. 이것은 일반적으로 물리학에 의해 처리됩니다.

전통적인 루프는 다음과 같습니다.

receive input
update physics
collision detection
collision resolution
render
repeat

게임 엔진이 절대 지오메트리를 테스트하여 충돌을 일으키는 경우는 드 rare니다. 일반적으로 알고리즘은 개요의 2 단계까지만 진행됩니다.
kevintodisco

대부분의 게임 엔진은 많은 경우에 절대 기하학을 테스트합니다. 그렇게하지 않으면 물리 반응에 매우 명백한 "결함"이있을 것입니다. 대부분의 엔진은 간단한 넓은 위상 (공간 분할), 간단한 바운딩 볼륨 테스트 (AABB가 가장 일반적), 단순화 된 지오메트리 테스트 (필요한 경우) 전체 LOD 렌더링 지오메트리와 같은 지오메트리를 갖지만 (필요한 경우) 렌더링 된 메시의 낮은 LOD 버전 중 하나 일 수있는 여전히 원시 지오메트리).
Sean Middleditch

@seanmiddleditch 필자는 대략 다각형이 다면체 / 다면체의 테스트를 피하려고 노력하면서 대략적인 테스트를 할 것이라는 의도를 가지고있었습니다.
gardian06

@ktodisco 그것은 그림의 오목 함과 그것이 얼마나 정확한지, 그리고 충돌을 해결하기 위해 물리 시스템이 무엇을 반환 해야하는지에 달려 있습니다. 물리 엔진과 물리 엔진의 의도 된 정확도에 따라 다를 수 있습니다. 응답
gardian06

@ guardian06 seanmiddleditch의 설명은 훨씬 더 실현 가능하지만 수천 개의 다각형으로 구성된 문자 간의 절대 교차를 테스트하는 것은 여전히 ​​좋은 생각이 아닙니다.
kevintodisco

1

그래픽 카드 수준 (일반적으로 삼각형을 다루는 곳)에서 일반적인 아이디어는 장면을 어떤 방식으로 분할하여 모든 N 삼각형을 확인할 필요가 없다는 것입니다 (이는 사전 처리 단계로 수행 할 수 있음) )을 누른 다음 장면의 현재 위치를 파악하고 해당 파티션에서 10-50 개의 삼각형 만 확인하십시오.

자세한 내용은 BSP 및 Kd 트리를 참조하십시오. 다른 파티셔닝 접근법도 있습니다.


0

첫째, 충돌 엔진의 가장 중요한 작업은 특정 상황에서 프레임별로 충돌을 검사 할 필요가없는 것을 프레임 단위로 확인하고 추가 검사에서 해당 객체를 제거하는 것입니다.

두 번째이지만 중요하지만 첫 번째 단계에서 수집되지 않은 나머지 개체에 대해 더 자세한 (정확한) 방식으로 확인하십시오.

셋째, 가장 효율적이고 적절한 방법을 사용하여 점검을 수행하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.