Bir çarpışma motoru nasıl çalışır?


78

Bir çarpışma motoru tam olarak nasıl çalışır?

Bu son derece geniş bir sorudur. Hangi kod bir şeyleri birbirine zıplatan tutar, oyuncunun duvardan yürümek yerine bir duvara girmesini sağlar? Kod, yerçekimi ve çarpışmanın gerektiği gibi çalışmasını sağlamak için oyuncuların pozisyonunu ve nesnelerin pozisyonunu sürekli olarak nasıl yeniliyor?

Bir çarpışma motorunun ne olduğunu bilmiyorsanız, temel olarak genellikle platform oyunlarında oyuncuyu keskin bir şekilde duvarlara ve benzerlerine vurmak için kullanılır. 2D tipi ve 3D tipi var, ancak hepsi aynı şeyi başardı: çarpışma.

Peki, çarpışma motorunu tıkayan ne?


3
Kesişimini belirlemek için hızlı olan sınırlayıcı kutular ve küreler ile hile yapabilirsiniz. O zaman daha yakından inceleyebilirsiniz. cs.unc.edu/~dm/collision.html en.wikipedia.org/wiki/Collision_detection Bunu her zaman saf bir algoritma ile yavaşça yapabilirsiniz. Comp Geometri, problemin geometrik yapısından faydalanan ve algoritmayı daha hızlı yapan bazı numaralara sahiptir. İşte çok iyi bir makale: cs.hku.hk/research/techreps/document/TR-2005-01.pdf

Bir nedir çarpışma motoru ?

4
Bir çarpışma motoru @gnat temelde oyunlarda kullanılan bir motordur (genellikle), böylece oyuncu bir bob bir duvara girdiğinde, oyuncu durur (bob olarak adlandırılır), bob durur, bob duvardan geçmez. Ayrıca genellikle bir oyunda yerçekimini ve bunun gibi çevresel şeyleri ele alırlar.
JXPheonix

Yanıtlar:


172

Bir çarpışma motoru ile bir fizik motoru arasında büyük bir fark var. Fizik motoru genellikle bir çarpışma motoruna dayanmasına rağmen, aynı şeyi yapmazlar.

Çarpışma motoru daha sonra iki bölüme ayrılır: çarpışma tespiti ve çarpışma tepkisi. Sonuncusu genellikle fizik motorunun bir parçasıdır. Bu nedenle çarpışma motorları ve fizik motorları genellikle aynı kütüphaneye taşınır.

Çarpışma tespiti, ayrık ve sürekli olmak üzere iki şekilde gelir. Gelişmiş motorlar, farklı özelliklere sahip oldukları için her ikisini de destekler. Genel olarak, sürekli çarpışma tespiti çok pahalıdır ve sadece gerçekten ihtiyaç duyulan yerlerde kullanılır. Çarpışma ve fiziğin çoğunluğu ayrık yöntemler kullanılarak ele alınmaktadır. Kesikli yöntemlerde nesneler birbirine nüfuz eder ve fizik motoru daha sonra onları birbirinden uzaklaştırmaya çalışır. Böylece motor bir oyuncunun kısmen bir duvardan veya zeminden yürümesini durdurmaz, oyuncunun kısmen duvar / yerde olduğunu tespit ettikten sonra sabitler. Burada ayrık çarpışma algılamaya odaklanacağım, çünkü sıfırdan uygulamada en çok deneyime sahip olduğum şey bu.

Çarpışma algılama

Çarpışma tespiti nispeten kolaydır. Her nesnenin bir dönüşümü ve bir şekli vardır (muhtemelen çoklu şekiller). Naif yaklaşımlar, çarpışma motorunun tüm nesne çifti boyunca bir O (n ^ 2) döngü yapmasını ve çiftler arasında çakışma olup olmadığını test etmesini sağlar. Daha akıllı yaklaşımlarda, birden fazla uzamsal veri yapısı (örneğin, statik ve dinamik nesneler için), her nesne için bir sınırlama şekli ve her nesne için çok parçalı dışbükey alt şekiller bulunur.

Mekansal veri yapıları, KD-Ağaçları, Dinamik AABB ağaçları, Octrees / Quadtrees, Binary Space Partitioning trees ve benzerlerini içerir. Her birinin avantajları ve dezavantajları vardır, bu yüzden bazı yüksek uçlu motorlar birden fazla kullanmaktadır. Örneğin Dinamik AABB ağaçları gerçekten çok hızlı ve çok sayıda hareketli nesneyi işlemek için iyidir; KD-Ağacı ise nesnelerin çarpıştığı statik seviye geometrisi için daha uygun olabilir. Başka seçenekler de var.

Geniş faz, uzamsal veri yapılarını ve her nesne için soyut bir sınırlayıcı hacmi kullanır. Sınırlayıcı bir hacim, tüm nesneyi saran basit bir şekildir, genellikle çarpışma testlerini yapmak için ucuza kalırken, mümkün olduğu kadar "sıkıca" tutma amacı ile. En yaygın sınırlama şekilleri, Eksen Hizalanmış Sınırlama Kutuları, Nesne Hizalanmış Sınırlama Kutuları, Küreler ve Kapsüller'dir. AABB'ler genellikle en hızlı ve en kolay olanı olarak kabul edilir (Bazı durumlarda küreler daha kolay ve daha hızlıdır, ancak bu uzamsal veri yapılarının birçoğu, kürenin yine de bir AABB'ye dönüştürülmesini gerektirecektir), ama aynı zamanda pek çok nesneye de zayıf bir şekilde sığma eğilimindedir. Kapsüller, karakter seviyesi çarpışmalarının üstesinden gelmek için 3D motorlarda popülerdir. Bazı motorlar iki sınırlama şekli kullanır,

Çarpışma tespitinin son aşaması, geometrinin kesiştiği yeri tam olarak tespit etmektir. Bu genellikle, her zaman olmasa da, bir ağın (ya da 2B'de çokgen) kullanılması anlamına gelir. Bu aşamanın amacı, nesnelerin gerçekten çarpışıp çarpışmadığını, ince bir ayrıntı seviyesinin gerekli olup olmadığını bulmaktır (örneğin, bir vurucuda mermi çarpışması, ancak zorlukla kaçıran çekimleri görmezden gelmek isteyebilirsiniz) ve Ayrıca nesnelerin tam olarak nerede çarpıştığını bulmak için, bu nesnelerin nasıl tepki vereceğini etkileyecektir. Örneğin, bir masanın kenarında oturan bir kutu varsa, motor masanın hangi noktalara karşı bastırdığını bilmelidir; Kutunun ne kadar asılı kaldığına bağlı olarak, kutu yana yatmaya ve düşmeye başlayabilir.

Manifold Üretimi

Burada kullanılan algoritmalar, popüler GJK ve Minkowski Portal İyileştirme algoritmalarını ve Ayırıcı Eksen testini içerir. Popüler algoritmalar genellikle yalnızca dışbükey şekiller için çalıştığından, birçok karmaşık nesneyi dışbükey alt nesnelere ayırmak ve her biri için ayrı ayrı çarpışma testleri yapmak gerekir. Bu, basitleştirilmiş kafeslerin sıklıkla çarpışma için kullanılmasının nedenlerinden biri ve ayrıca daha az üçgen kullanmak için işlem süresindeki azalmanın bir nedenidir.

Bu algoritmaların bazıları size yalnızca nesnelerin kesin olarak çarpıştığını değil, aynı zamanda nerede çarpıştığını da söyler - birbirlerinden ne kadar içeri girdiklerini ve “temas noktalarının” ne olduğunu. Algoritmaların bazıları, bu bilgiyi elde etmek için çokgen kırpma gibi ek adımlar gerektirir.

Fiziksel Tepki

Bu noktada, bir temas keşfedildi ve fizik motorunun kontağı işlemesi için yeterli bilgi var. Fizik kullanımı çok karmaşık olabilir. Basit algoritmalar bazı oyunlar için işe yarar, ancak bir kutu yığını sabit tutmak kadar basit görünen bir şey bile oldukça zordur ve çok fazla çalışma ve açık olmayan kesimler gerektirir.

En temel seviyede, fizik motoru bunun gibi bir şey yapacak: çarpışan nesneleri ve onların temas manifoldunu alacak ve çarpışan nesneleri ayırmak için gereken yeni konumları hesaplayacaktır. Nesneleri bu yeni pozisyonlara taşıyacaktır. Ayrıca bu itmeden kaynaklanan hız değişimini, restitüsyon (sıçrama) ve sürtünme değerleri ile birlikte hesaplayacaktır. Fizik motoru aynı zamanda nesnelerin yeni hızlarını hesaplamak için yerçekimi gibi nesnelere etki eden diğer kuvvetleri de uygulayacak ve daha sonra yeni konumlarını hesaplayacaktır.

Daha ileri fizik tepkisi hızla karmaşıklaşıyor. Yukarıdaki yaklaşım, diğerlerinin üzerinde oturan bir nesne dahil olmak üzere birçok durumda yıkılacaktır. Her bir çift ile başa çıkmak "titremeye" neden olur ve nesneler çok fazla zıplar. En temel teknik, çarpışan nesne çiftleri üzerinde bir dizi hız-düzeltme yinelemesi yapmaktır. Örneğin, "B" ve "C" diğer iki kutunun üstüne oturmuş bir "A" kutusuyla, önce AB çarpışması gerçekleştirilir, bu da A kutusunun C kutusuna daha fazla eğilmesine neden olur. Sonra AC çarpışması gerçekleştirilir. kutuları biraz dışarı çıkartın, ancak A'yı aşağı ve B'ye doğru çekin. Daha sonra başka bir yineleme yapılır, böylece AC düzeltmesinin neden olduğu AB hatası, AC yanıtında biraz daha fazla hata yaratarak hafifçe giderilir. AC tekrar işlendiğinde ele alınır. Yapılan yineleme sayısı sabit değildir ve “mükemmel” olduğu bir nokta yoktur, ancak ne kadar sayıda yineleme anlamlı sonuç verirse durursa dursun. 10 yineleme tipik bir ilk denemedir, ancak belirli bir motor ve belirli bir oyunun ihtiyaçları için en iyi rakamı bulmak için ince ayar yapılması gerekir.

Önbelleğe Alma

Birçok oyun türüyle uğraşırken gerçekten kullanışlı (ya da daha az gerekli) olduğu ortaya çıkan başka numaralar da vardır. Kontakt önbellekleme daha faydalı olanlardan biridir. Bir kişi önbelleğiyle, her bir çarpışan nesne kümesi arama tablosuna kaydedilir. Bir çarpışma algılandığında, her kare, nesnelerin daha önce temas halinde olup olmadığını görmek için bu önbellek sorgulanır. Nesneler daha önce temas halinde değilse, "yeni bir çarpışma" olayı oluşturulabilir. Nesneler daha önce temas halindeyse, bilgi daha istikrarlı bir yanıt sağlamak için kullanılabilir. Kişi önbelleğindeki bir çerçevede güncellenmeyen tüm girişler, birbirinden ayrılan iki nesneyi gösterir ve "ayırma nesnesi" olayı oluşturulabilir. Oyun mantığı genellikle bu olaylar için kullanır.

Oyun mantığının yeni çarpışma olaylarına cevap vermesi ve bunları göz ardı edilmiş olarak işaretlemesi de mümkündür. Bu, platformlarda sıkça karşılaşabileceğiniz, ancak üzerine çıkabileceğiniz platformlar gibi bazı özellikleri uygulamak için gerçekten yararlıdır. Naif uygulamalar, aşağı doğru platform-> karakter çarpışması normal olan çarpışmaları görmezden gelebilir (oyuncunun başının platformun dibine vurduğunu gösterir), ancak temas önbelleğe alma olmadan, oyuncunun kafası platformun içinden yükselir ve sonra başlarsa kırılır düşmek. Bu noktada normal temas, yukarı bakacak ve oyuncunun yapmaması gerektiğinde platformdan çıkmasına neden olabilir. Temas önbelleğe alma ile motor, ilk çarpışmaya normal şekilde güvenilir şekilde bakabilir ve platform ile oynatıcı tekrar ayrılana kadar tüm diğer temas olaylarını görmezden gelebilir.

Uyuyor

Çok kullanışlı bir teknik de, nesneleri etkileşime girmedikleri takdirde "uykuda" olarak işaretlemektir. Uyuyan nesneler fizik güncellemesi almazlar, diğer uyuyan nesnelerle çarpışmazlar ve temel olarak sadece uykuda olmayan başka bir nesne onlarla çarpışana kadar zaman içerisinde donmuş olarak otururlar.

Bunun etkisi, orada oturan hiçbir şey yapmayan çarpışan nesnelerin çiftlerinin hiçbir işlem zaman almamasıdır. Ayrıca, sabit miktarda küçük fizik düzeltmesi olmadığı için, yığınlar sabit kalacaktır.

Bir nesne, tek bir kareden daha fazlası için sıfıra yakın bir hıza sahip olduğunda uyumak için adaydır. Bu sıfıra yakın hızı test etmek için kullandığınız epsilonun, yığılmış nesnelerle bir miktar titremeyi beklemeniz gerektiğinden, normal kayan nokta karşılaştırma epsilonundan biraz daha yüksek olacağını ve eğer varsa tüm nesnelerin uykuya dalmasını istediğinizi unutmayın. İstikrar için "yeterince yakın" kalıyorsun Eşik elbette ince ayar ve deneme gerektirecektir.

Kısıtlamalar

Birçok fizik motorunun son büyük kısmı kısıtlayıcı çözücüdür. Böyle bir sistemin amacı, yaylar, motorlar, tekerlek ekseni, simüle edilmiş yumuşak gövdeler, kumaşlar, halatlar ve zincirler ve bazen de sıvı gibi şeylerin uygulanmasını kolaylaştırmaktır (akışkan, genellikle tamamen farklı bir sistem olarak uygulanır).

Kısıtlama çözümünün temelleri bile çok matematik yoğunlaşabilir ve bu konudaki uzmanlığımın ötesine geçebilir. Konunun daha ayrıntılı bir açıklaması için Randy Gaul'un fizikle ilgili mükemmel yazı dizisini incelemenizi öneririm .


Minimum çarpışma çözünürlüğü sayısını ele alacaksanız, o zaman muhtemelen yüksek sayıdaki çarpışma havuzuna izin veren karmaşık bir kurulumda kare hızını büyük ölçüde azaltacağını düşünerek sayının olabildiğince düşük tutulması gerekliliğini de ele almalısınız. o zaman yineleme sayısından bahsettikten sonra her çift için olan oydu ya da tüm çarpışmalar için.
gardian06

1
@ gardian06: hızlıca yazılmış bir bakış, biraz genişletilebileceğinden emin. Mesela, oldukça yararlı olan, uykuda nesneden bahsetmeyi unuttum. Yinelemeler için, çiftlerin tüm koleksiyonlarını yineliyorum ve nispeten büyük yineleme sayılarıyla bile (20+) Performans sorunu fark etmedim (ama yine de, nesnenin uykusu ile, bu yüzden çözülmesi için nispeten az sayıda aktif çarpışma var) ).
Sean Middleditch

1
Harika cevap, +1. Bunu okumak gerçekten bu algoritmaları uygulamak istememi sağlıyor.
Miles Rout

3

Genel sorun: nesnelerin olası tüm kombinasyonlarından hangisinin sıfır kesişmeyen birime sahip olduğunu belirleyin.

Saf, genel yaklaşım basittir: Her olası nesne çifti için kesişme hacmini hesaplayın. Bu genellikle pratik değildir, çünkü O (n ^ 2) nispeten pahalı kesişme işlemlerini gerektirir.

Bu nedenle, pratik uygulamalar genellikle uzmanlaşmıştır ve kesişen kontrollerden kaçınılması veya maliyetlerinin düşürülmesine izin vermek için bazı varsayımlar yapmaktadır. Mekansal bölümleme, nesnelerin toplam hacme göre tipik olarak küçük olması ve tipik olarak O (n log n) ile karşılaştırma sayısını azaltacağı gerçeğinden yararlanır. Eksen hizalı sınırlayıcı kutular ve sınırlayıcı küreler, nesneler belirli kompaktlık varsayımlarına uyduğu sürece ucuz kaba kesişme kontrolleri sağlar. Ve bunun gibi.


2

Kullandığım bir "çarpışma motoru" kavraması son derece kolaydı.

Temel olarak, API, yöntemi olan bir tür nesne sağladı collidesWith.

  1. parametreleri, çarpışma için “uygun” olan farklı nesnelerdi.
  2. çarpışmanın olup olmamasına bağlı olarak doğru veya yanlış olarak döndü
  3. nesneler için tüm sınırlayıcı dikdörtgenlerin çarpışma olayını tetikleyip tetiklememesini seçmeye izin veren bir seçenek vardı, ya da sadece bu dikdörtgenler içindeki opak pikselleri (piksel seviyesi algılama)

Başvurumda collidesWithçarpışmanın olup olmadığını öğrenmek için düzenli aralıklarla çağrıldım .

Oldukça basit değil mi?


Belki küçük bir hayal gücü gerektiren tek şey, düz sınırlayıcı dikdörtgenlerin çarpışan nesnelerin geometrisini simüle etmek için yeterli olmadığı durumdaydı. Bu durumda bir tane yerine bir kaç tane çarpışan nesne kullanmak zorunda kalacaksınız.

Genel olarak, tek bir çarpışma dikdörtgeninin ihtiyacınız olanı yapmadığını tespit ettiğinizde, şeyleri daha dikdörtgen alt öğelere ayrıştırmanın bir yolunu bulursunuz, böylece birleştirildiğinde bu öğeler istenen davranışı simüle eder / yaklaşık olarak gösterir.

  • Son kullanıcılar sahnenin arkasında kaç tane nesne bulunduğunu önemsemiyor. Sonuç, bekledikleri gibi hissettirdiği sürece mutlular, örneğin, etrafını çevreleyen arka bahçe çitleri gibi bir ev gibi:

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


2

Bence neden bahsettiğin konusunda kafan biraz karıştı ve birkaç farklı şeyden bahsediyorsun.

Bu maddenin X konumundan Y konumuna taşındığını söyleyebilme yeteneği fiziğe dayanmaktadır (bu aynı zamanda nasıl hareket ettikleri ve neden hareket ettikleri hakkında da saldırılar yapar)

çarpışma tespiti için kullanılan yöntem oyununuzun yapısına göre belirlenir. Eğer oyununuz büyük bir açık dünyaysa, o zaman büyük ölçüde uzay bölümlemesini düşünmelisiniz (dörtlü ağaç [3B için oct ağacı], BSP, geleneksel bir ızgara veya eski moda test her şey yaklaşıyor)

Bir çarpışma tespit sistemi uygulamanın en iyi yolu, bunu adım adım yapmaktır.

  1. Tüm nesneleri genel sınırlayıcı birime / şekle yerleştirin ve sonra bunları test edin.

  2. 1 geçilirse mutlak geometriyi test etmeye hazır olana kadar daha karmaşık bir hacim / şekil tekrarı ile tekrarlayın

  3. mutlak geometriyi test edin, 2. adımı tekrarladığınız zaman, şekillerin karmaşıklığına ve bu şekillerin ne kadar doğru olduğuna karar verilmelidir.

bu adımların her birinin erken çıktığını ve ilerledikçe çarpışmaları gidermek ve sadece gerçekten dokunuyorsanız 3. adımda doğru dönmek amacıyla düşünmeniz gerekir.

Son bölüm ise çarpışma çözünürlüğüdür. bu, bir çarpışma bulduktan sonra neler olacağını ve bunun gerçekten bir çarpışma olduğunu kanıtladıktan ve bununla ilgili ne yapacağınızı belirler. bu genellikle fizik tarafından gerçekleştirilir.

geleneksel döngü şöyle görünür:

receive input
update physics
collision detection
collision resolution
render
repeat

Sadece oyun motorlarının çarpışmalar için mutlak geometri testine girmesinin nadir olduğunu belirtmek isterim. Genellikle, algoritma yalnızca anahatlarınızdaki 2. adıma kadar gider.
kevintodisco

Çoğu oyun motoru, çoğu (hepsi değil) durumlarda mutlak geometriyi test eder. Bunu yapmadan fizik cevabında çok açık bir şekilde "aksaklıklar" olacaktır. Çoğu motor basit bir geniş faza (uzamsal bölümleme), basit bir sınırlayıcı hacim testine (en sık AABB) ve sonra (gerektiğinde) basitleştirilmiş bir geometri testine (örneğin, tam LOD işleme geometrisi ile aynı geometriye sahip değil) sahip olacaktır. hala işlenmiş ağın düşük LOD versiyonlarından biri olan ham geometri).
Sean Middleditch

Daha fazla niyetim olan seanmiddleditch, genellikle içbükey çokgen / çokyüzlilerin test edilmesini önlemek için bir yaklaşımın test edilmesini sağlamaktı.
gardian06

ktodisco bu rakamın tutarlılığına, ne kadar doğru olması gerektiğine ve sonra fiziğin motorunun temeline göre değişebileceğinden çarpışmayı çözmek için fizik sistemine ne gibi ihtiyaç duyulduğuna ve bunun amaçlanan doğruluğuna bağlıdır. yanıt
gardian06

@ guardian06 seanmiddleditch'in açıklaması çok daha uygun, ancak binlerce poligondan oluşan karakterler arasındaki kesin kesişme testleri hala iyi bir fikir değil.
kevintodisco

1

Grafik kartı düzeyinde (genellikle üçgenlerle uğraştığınız), genel fikir sahneyi bir şekilde bölümlere ayırmaktır, böylece tüm N üçgenlerini kontrol etmek zorunda kalmazsınız (bu işlem öncesi bir adım olarak yapılabilir) ) ve ardından sahnede nerede olduğunuzu öğrenin ve yalnızca bu bölümdeki 10-50 üçgeni kontrol edin.

Daha fazla bilgi için BSP ve Kd ağaçlarına bakınız. Başka bölümlendirme yaklaşımları da var.


0

Öncelikle, bir çarpışma motorunun en önemli işinin herhangi bir özel durumda herhangi bir durumda çarpışma için neyin kontrol edilmesine gerek olmadığını belirlemek ve bu nesneleri daha fazla kontrolden çıkarmak olduğunu düşünüyorum.

İkincil, ama aynı zamanda önemli, ilk adımda toplanmamış nesnelere karşı daha ayrıntılı (doğru) bir şekilde kontrol edin.

Üçüncüsü, kontrolleri gerçekleştirmek için en verimli / uygun yöntemleri kullanın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.