더 빠른 2D 충돌 감지


13

최근에 나는 빠르게 진행되는 2D 사수를 연구하고 있었고 큰 문제를 겪었습니다. 충돌 감지. 물론 작동하지만 매우 느립니다. 내 목표는 : 화면에 많은 적을 가지고 서로 접촉하지 않도록하십시오. 모든 적들이 플레이어 개체를 쫓고 있습니다. 그들 대부분은 조만간 같은 속도를 가지므로 플레이어를 쫓으면서 같은 공간을 차지하게됩니다. 이것은 플레이어가 하나의 적에게만 쫓기고있는 것처럼 보이기 때문에 재미있는 요소를 떨어 뜨립니다. 그들이 같은 공간을 차지하지 못하도록 충돌 감지 (내가 아는 유일한 방법 인 매우 기본적인 2D 감지)를 추가했습니다.

Enemy class update method
    Loop through all enemies (continue; if the loop points at this object)
        If enemy object intersects with this object
            Push enemy object away from this enemy object

이것은 잘 작동합니다. 내가 200 명 미만의 적 개체 만있는 한. 300 ~ 350 개의 적군 개체에 가까워지면 프레임 속도가 크게 떨어지기 시작합니다. 먼저 렌더링이 잘못되었다고 생각하여 그리기 호출을 제거했습니다. 이것은 물론 전혀 도움이되지 않았습니다. 업데이트 방법이라는 것을 깨달았습니다. 그들의 업데이트 방법에서 유일하게 큰 부분은이 각 루프를 통한 모든 에너미 부분입니다. 300 명에 가까워지면 게임은 90000 (300x300)의 스텝 이터 레이션을 수행합니다. 내 ~

이 충돌 감지에 접근 할 수있는 다른 방법이 있어야합니다. 나는 방법을 모른다. 내가 찾은 페이지는 실제로 두 객체 간의 충돌을 수행하는 방법 또는 객체와 타일 간의 충돌을 확인하는 방법에 관한 것입니다. 나는 이미 그 두 가지를 알고 있습니다.

tl; dr? 엔터티의 LOTS간에 충돌 감지를 어떻게 수행합니까?

빠른 편집 : 도움이 필요하면 C # XNA를 사용하고 있습니다.


처음에 90K로 가려면 어떻게되는지 궁금합니다. 광산은 20K로 질식합니다 (완전 SAT MTV 감지를하고 있습니다). 그러나 나는 모든 원수를 반복하는 것이 가능한 것 같습니다. 그러나 이미 확인했는지 확인해야합니다. 말을 좋아하면 모두가 두 번 모두 테스트를 받고 있기 때문입니다.
망상 논리


@MarkusvonBroady가 ​​연결 한 질문에는 아주 좋은 대답이 있습니다.
Cypher

답변:


11

당신은 이미 머리에 문제를 바로 쳤고, 모든 엔티티가 다른 모든 엔티티와 대조되도록했습니다. 당신이 원하는 것은 가능한 충돌 후보가 더 잘 선택되는 일종의 'Level of Detail'시스템 유형입니다 (거의 매우 간단한 장면 그래프, 렌더링 이외의 용도로 사용하고 있습니다).

나는 일반적으로 이와 같은 시스템을 위해 세 가지 컬렉션을 수행합니다. 추적하려는 데이터 (다른 모든 항목에 대한 항목이있는 항목 당 3 개의 목록)가 빠르게 나올 수 있기 때문에 원하는 엔티티 수에 대해 이야기 할 때 전체 장면 그래프를 사용해야 할 수도 있습니다. 통제의.

기본적으로 세 가지 목록이 있습니다. 첫 번째는 매우 작은 엔티티 목록이어야하며 매 프레임마다 상호 작용으로 확인할 것입니다. 이들은 해당 엔티티의 X 범위 내에 있기 때문에이를 결정합니다. 언급 한 바와 같이이 목록의 요점은 다른 프레임과 합리적으로 충돌 할 수있는 모든 엔티티를 포함하는 것입니다.

다음리스트는 너무 많은 노력없이 엔티티의 범위로 이동할 수있는 버퍼 범위에있는 것입니다. 우리는이 범위를 X * 1.5라고 부릅니다. 이것은 프레임 당 몇 개만 업데이트하지만 매끄럽게 작동하는 모양을 유지할 수있을 정도로 빠르게 진행되도록하는 시간 분할 목록입니다.

세 번째 목록은 '다른 모든 것'목록이며이 목록이 가치가없는 것을 피하는 방법입니다 (전체 엔티티 목록을 스캔하고 진행하기 전에 다른 목록 중 하나에 있는지 확인하고 있습니까? 목록 크기에 따라 이 목록의 개체는 다른 두 목록 중 하나에 배치 할 프레임이 몇 개 이상 있어야하므로 확인해야합니다.

이를 유지하기 위해해야 ​​할 일은 충돌 테스트를 수행 할 때, 엔티티가있는 목록을 업데이트해야합니다. 범위를 벗어난 항목은 다운 그레이드해야하고, 더 가까이 이동하는 항목도 업그레이드해야합니다. 더 적극적으로 확인 된 목록.

당신이 이것을 당신의 필요에 맞게 충분히 단순하게 유지한다고 가정하십시오. 기존 렌더링 장면 그래프에 추가 정보를 추가 할 수있는 경우 (있는 경우) 장면 그래프의 전체 지점보다 더 나은 범위 내에있는 엔티티 목록을 가져 오도록 쿼리 할 수 ​​있습니다. 어쨌든 (위치에 따라 관련 데이터 목록에 빠르게 액세스). 이를 위해서는 잠재적으로 더 많은 작업이 필요하므로 실제로 수행해야하는 작업과 수행해야하는 작업을 항상 고려해야합니다.

도움이 되었기를 바랍니다.


1
이것은 모호한 답변입니다. 그리고 우리는 충돌을 놓칠 수 있습니까 ?? 훨씬 간단하게 여기에서 이야기하는 쿼드 트리와 같이 표면 파티셔닝을 수행하는 데이터 구조를 사용하십시오. 쿼드 트리조차도 오버 헤드를 피하기 위해 약간의 미세 조정이 필요하므로 이야기하는 '솔루션'의 복잡성을 상상할 수 없습니다. 기본 프로그래밍 규칙 : 올바른 데이터 구조를 사용하십시오.
GameAlchemist

@VincentPiel 장면 그래프는 쿼드 트리보다 복잡하지 않습니다.
Cypher

@ 제임스 : 분명히 더 복잡합니다. QuadTree의 최고 속도를 파악하지 않으려면, 인터넷에서 QuadTree 라이브러리를 가져 와서 몇 시간 안에 완벽하게 작동시킬 수 있습니다. 같은 질문 없음 : 첫 번째 목록에 두 번째, 세 번째, 세 번째, 엔티티를 다른 목록에 넣는 방법을 결정하고 충돌을 놓치지 마십시오. 차를 가질 수 있는데 왜 자전거를 사용합니까?
GameAlchemist

@VincentPiel 나는 당신이 여기 @ 대신 Cypher에 대한 귀하의 의견을 의미한다고 생각합니다. 쿼드 트리는 일종의 장면 그래프 일 뿐이므로 초당 X 프레임으로 실행 중임을 기억해야합니다. 누락 된 충돌을 발견 한 경우 범위 임계 값을 조정하여 균형을 더 잘 맞출 필요가 있습니다. 내 솔루션은 매우 간단한 접근 방식으로 충돌 할 가능성이있는 모든 프레임 만 확인한 다음 나머지에서 백그라운드 / 제한 업데이트를 수행하여 더 높은 우선 순위에 해당하는지 확인합니다.
James

6

정렬 된 데이터 구조와의 충돌을 처리해야하므로 끔찍한 n ^ 2 대신 n * log (n) 번을 사용할 수 있습니다. 그리고 n * log (n)은 아시다시피 거의 선형입니다. 하나의 (고전적인) 예제는 quadtree이며, 여기에는 그래픽과 코드 (Java)가 포함 된 매우 간단하고 잘 작성된 자습서가 있습니다.

http://gamedev.tutsplus.com/tutorials/implementation/quick-tip-use-quadtrees-to-detect-likely-collisions-in-2d-space/

Rq : 어떤 언어로든 QuadTrees에 대한 구현을 찾기가 매우 쉽습니다. 여전히, 당신은 나무에 대한 올바른 '과립 성'에 대해 생각해야하고, 나무 크기가 클수록 우리는 노드에 맞지 않는 엔티티를 더 많이 갖게됩니다.
Rq 2 : 공간 분할은 충돌 감지를 위해서만 수행되므로 원하는대로 공간을 자유롭게 분할 할 수 있습니다. 예를 들어, 나는 네 개의 egal 부분으로 나누지 않고 오히려 현재 레벨 엔티티의 baricenter를 새로운 나누기의 중심으로 사용합니다. 1) 알고리즘은 여전히 ​​n * log (n)입니다 .2) 트리에서 장면을 '재 빌드'할 가능성을 잃어 버립니다. 그러나 상관하지 않습니다. .
Rq3 : 일단 나무가 생기면 화면과 엔티티 사이의 '충돌'이 가시적 인 엔티티를 제공합니다! log (n)과 같은 시간에 n이 큰 이유는 무엇입니까? (이 방법의 경우 최악의 경우는 n의 시간입니다.)


네, 쿼드 트리는 실제로 일종의 장면 그래프입니다. 나는 항상 여기에있는 사람들이 다른 사람들의 라이브러리를 사용하지 않고 직접 물건을 쓰고 싶어한다고 가정합니다.이 경우 쿼드 트리에서 멈추고 완전한 충돌 라이브러리를 찾으십시오.
James

0

이진 공간 파티션 트리, quadtree, octree (3D 용)는 충돌을 적용하려는 모든 객체에 대한 모든 업데이트 호출에서 생성 (또는 야심이있는 경우 유지 관리) 할 수있는 트리입니다.


3
이것은 의견에 더 적합합니다. 답을 더 추가해보십시오.

0

대화가 쿼드 또는 옥트 트리에 관해 올 때 나는 매우 순진합니다. 그러나 나는이 방법이해야한다고 생각합니다.

플레이어 구조 / 클래스를 수정해야합니다. 다른 플레이어 구조에 대한 포인터 배열 / 벡터를 추가하십시오.

두 선수 사이의 매 초마다 거리를 확인하십시오. 1 초 내에 도달 할 수 없을 정도로 낮은 경우, 해당 플레이어의 포인터를 현재 플레이어의 충돌 배열에 추가하십시오.

이제 서로 목록에있는 플레이어 간의 충돌 만 확인하십시오.

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