Làm thế nào để một động cơ va chạm làm việc?


78

Làm thế nào chính xác một động cơ va chạm làm việc?

Đây là một câu hỏi cực kỳ rộng. Mã nào giữ cho mọi thứ nảy lên với nhau, mã nào khiến người chơi bước vào tường thay vì đi xuyên tường? Làm thế nào để mã liên tục làm mới vị trí của người chơi và vị trí đối tượng để giữ trọng lực và va chạm làm việc như bình thường?

Nếu bạn không biết động cơ va chạm là gì, về cơ bản, nó thường được sử dụng trong các trò chơi nền tảng để khiến người chơi đánh mạnh vào tường và những thứ tương tự. Có loại 2D và loại 3D, nhưng tất cả đều hoàn thành cùng một thứ: va chạm.

Vì vậy, những gì giữ một động cơ va chạm tích tắc?


3
Bạn có thể gian lận với các hộp và hình cầu giới hạn, giao điểm của nó rất nhanh để xác định. Sau đó, bạn có thể kiểm tra chặt chẽ hơn. cs.unc.edu/~dm/collision.html en.wikipedia.org/wiki/Collision_detection Bạn luôn có thể làm điều này từ từ với thuật toán ngây thơ. Comp Geometry có một số thủ thuật lợi dụng bản chất hình học của vấn đề và làm cho thuật toán nhanh hơn. Đây là một bài viết rất hay: cs.hku.hk/research/techreps/document/TR-2005-01.pdf

một là những gì cơ va chạm ?

4
@gnat một động cơ va chạm về cơ bản là một động cơ được sử dụng trong các trò chơi (nói chung) để người chơi của bạn (gọi anh ta là bob), bất cứ khi nào bob di chuyển vào tường, bob dừng lại, bob không đi qua tường. Họ cũng thường xử lý trọng lực trong một trò chơi và những thứ môi trường như thế.
JXPheonix

Câu trả lời:


172

Có một sự khác biệt lớn giữa động cơ va chạm và động cơ vật lý. Họ không làm điều tương tự, mặc dù động cơ vật lý thường dựa vào động cơ va chạm.

Động cơ va chạm sau đó được chia thành hai phần: phát hiện va chạm và phản ứng va chạm. Cái sau nói chung là một phần của động cơ vật lý. Đây là lý do tại sao động cơ va chạm và động cơ vật lý thường được đưa vào cùng một thư viện.

Phát hiện va chạm có hai dạng, rời rạc và liên tục. Động cơ tiên tiến hỗ trợ cả hai, vì chúng có các thuộc tính khác nhau. Nói chung, phát hiện va chạm liên tục là rất tốn kém và chỉ được sử dụng khi thực sự cần thiết. Phần lớn va chạm và vật lý được xử lý bằng các phương pháp rời rạc. Trong các phương pháp riêng biệt, các vật thể cuối cùng sẽ thâm nhập lẫn nhau, và động cơ vật lý sau đó hoạt động để đẩy chúng ra xa nhau. Vì vậy, động cơ không thực sự ngăn người chơi đi một phần qua tường hoặc sàn, nó chỉ sửa nó sau khi phát hiện ra rằng người chơi đang ở một phần trên tường / sàn. Tôi sẽ tập trung vào phát hiện va chạm rời rạc ở đây, vì đó là điều tôi có nhiều kinh nghiệm nhất khi thực hiện từ đầu.

Phát hiện va chạm

Phát hiện va chạm là tương đối dễ dàng. Mỗi đối tượng có một biến đổi và một hình dạng (có thể nhiều hình dạng). Các cách tiếp cận ngây thơ sẽ có động cơ va chạm thực hiện một vòng lặp O (n ^ 2) thông qua tất cả các cặp đối tượng và kiểm tra nếu có sự chồng chéo giữa các cặp. Trong các cách tiếp cận thông minh hơn, có nhiều cấu trúc dữ liệu không gian (ví dụ: đối với các đối tượng tĩnh so với động), hình dạng giới hạn cho từng đối tượng và hình dạng con lồi đa phần cho mỗi đối tượng.

Các cấu trúc dữ liệu không gian bao gồm những thứ như cây KD, cây AABB động, cây Octrees / Quadtrees, cây phân vùng không gian nhị phân, v.v. Mỗi cái đều có ưu điểm và nhược điểm, đó là lý do tại sao một số động cơ cao cấp hơn sử dụng nhiều hơn một. Chẳng hạn, cây AABB động thực sự rất nhanh và tốt để xử lý nhiều đối tượng chuyển động trong khi Cây KD có thể phù hợp hơn với hình dạng mức tĩnh mà các đối tượng va chạm. Có những lựa chọn khác là tốt.

Pha rộng sử dụng các cấu trúc dữ liệu không gian và khối lượng giới hạn trừu tượng cho từng đối tượng. Một khối lượng giới hạn là một hình dạng đơn giản bao quanh toàn bộ đối tượng, thường với mục tiêu bao quanh nó là "chặt chẽ" nhất có thể trong khi vẫn rẻ để thực hiện các thử nghiệm va chạm. Các hình dạng giới hạn phổ biến nhất là Hộp giới hạn theo trục, Hộp giới hạn đối tượng, Hình cầu và Viên nang. AABB thường được coi là nhanh nhất và dễ nhất (Sphere dễ dàng hơn và nhanh hơn trong một số trường hợp, nhưng nhiều cấu trúc dữ liệu không gian đó sẽ yêu cầu chuyển đổi hình cầu thành AABB), nhưng chúng cũng có xu hướng phù hợp với nhiều đối tượng khá kém. Viên nang là phổ biến trong các công cụ 3D để xử lý các va chạm ở cấp độ nhân vật. Một số động cơ sẽ sử dụng hai hình dạng giới hạn,

Giai đoạn cuối cùng của phát hiện va chạm là phát hiện chính xác nơi hình học đang giao nhau. Điều này thường ngụ ý sử dụng lưới (hoặc đa giác trong 2D), mặc dù không phải lúc nào cũng vậy. Mục đích của giai đoạn này là tìm hiểu xem các vật thể có thực sự va chạm hay không, nếu cần một mức độ chi tiết tốt (giả sử, va chạm đạn trong một game bắn súng, nơi bạn muốn có thể bỏ qua những phát bắn mà hầu như không bỏ lỡ), và cũng để tìm ra chính xác nơi các đối tượng va chạm, điều này sẽ ảnh hưởng đến cách các đối tượng phản ứng. Ví dụ, nếu một hộp đang ngồi trên cạnh của bàn, động cơ phải biết tại điểm nào mà bàn đang đẩy vào hộp; tùy thuộc vào khoảng cách của hộp treo, hộp có thể bắt đầu nghiêng và rơi ra.

Liên hệ thế hệ Manifold

Các thuật toán được sử dụng ở đây bao gồm các thuật toán sàng lọc Cổng thông tin GJK và Minkowski phổ biến, cũng như thử nghiệm Trục tách. Bởi vì các thuật toán phổ biến thường chỉ hoạt động cho các hình dạng lồi, nên cần phải chia nhiều đối tượng phức tạp thành các đối tượng phụ lồi và thực hiện các thử nghiệm va chạm cho từng cá nhân. Đây là một trong những lý do tại sao các lưới đơn giản hóa thường được sử dụng để va chạm, cũng như giảm thời gian xử lý để sử dụng ít hình tam giác hơn.

Một số thuật toán này không chỉ cho bạn biết rằng các vật thể đã va chạm chắc chắn, mà là nơi chúng va chạm - chúng cách nhau bao xa và "điểm tiếp xúc" là gì. Một số thuật toán yêu cầu các bước bổ sung, chẳng hạn như cắt đa giác, để có được thông tin này.

Phản ứng vật lý

Tại thời điểm này, một liên hệ đã được phát hiện và có đủ thông tin để động cơ vật lý xử lý liên hệ. Việc xử lý vật lý có thể rất phức tạp. Các thuật toán đơn giản hơn hoạt động cho một số trò chơi, nhưng ngay cả một thứ gì đó có vẻ đơn giản như việc giữ một chồng hộp ổn định hóa ra lại khá khó khăn và đòi hỏi nhiều công việc và hack không rõ ràng.

Ở cấp độ cơ bản nhất, động cơ vật lý sẽ làm một cái gì đó như thế này: nó sẽ lấy các vật thể va chạm và đa tạp tiếp xúc của chúng và tính toán các vị trí mới cần thiết để tách các vật thể va chạm. Nó sẽ di chuyển các đối tượng đến các vị trí mới. Nó cũng sẽ tính toán sự thay đổi vận tốc do lực đẩy này, kết hợp với sự phục hồi (độ nảy) và giá trị ma sát. Động cơ vật lý cũng sẽ áp dụng bất kỳ lực nào khác tác dụng lên các vật thể, chẳng hạn như trọng lực, để tính vận tốc mới của vật thể, và sau đó (khung tiếp theo) vị trí mới của chúng.

Phản ứng vật lý tiên tiến hơn trở nên phức tạp một cách nhanh chóng. Cách tiếp cận ở trên sẽ bị phá vỡ trong nhiều tình huống, bao gồm một đối tượng ngồi trên hai đối tượng khác. Đối phó với mỗi cặp tự nó sẽ gây ra "jitter" và các đối tượng sẽ nảy xung quanh rất nhiều. Kỹ thuật cơ bản nhất là thực hiện một số lần lặp hiệu chỉnh vận tốc trên các cặp vật thể va chạm. Ví dụ: với hộp "A" nằm trên hai hộp khác "B" và "C", va chạm AB sẽ được xử lý trước, khiến hộp A nghiêng thêm vào hộp C. Sau đó, va chạm AC được xử lý, buổi tối ra khỏi hộp một chút, nhưng kéo A xuống và vào B. Sau đó, một lần lặp khác được thực hiện, do đó lỗi AB gây ra bởi hiệu chỉnh AC được giải quyết một chút, tạo ra một chút lỗi trong phản hồi AC. Mà được xử lý khi AC được xử lý lại. Số lần lặp được thực hiện không cố định và không có điểm nào mà nó trở nên "hoàn hảo", mà chỉ là bất cứ số lần lặp nào dừng lại đều cho kết quả có ý nghĩa. 10 lần lặp là lần thử đầu tiên điển hình, nhưng cần phải điều chỉnh để tìm ra con số tốt nhất cho một công cụ cụ thể và nhu cầu của một trò chơi cụ thể.

Liên lạc bộ nhớ đệm

Có những thủ thuật khác hóa ra thực sự tiện dụng (ít nhiều cần thiết) khi xử lý nhiều loại trò chơi. Liên lạc bộ nhớ đệm là một trong những người hữu ích hơn. Với bộ đệm liên hệ, mỗi bộ đối tượng va chạm được lưu trong bảng tra cứu. Mỗi khung hình, khi phát hiện xung đột, bộ đệm này được truy vấn để xem các đối tượng trước đó có tiếp xúc hay không. Nếu các đối tượng trước đây không tiếp xúc, thì có thể tạo ra sự kiện "va chạm mới". Nếu các đối tượng trước đây đã tiếp xúc, thông tin có thể được sử dụng để cung cấp phản hồi ổn định hơn. Bất kỳ mục nào trong bộ đệm liên hệ không được cập nhật trong khung cho biết hai đối tượng được phân tách và có thể tạo sự kiện "tách đối tượng". Logic trò chơi thường có sử dụng cho các sự kiện này.

Logic trò chơi cũng có thể phản ứng với các sự kiện va chạm mới và gắn cờ chúng là bị bỏ qua. Điều này thực sự hữu ích để triển khai một số tính năng phổ biến trong các nền tảng, như các nền tảng mà bạn có thể nhảy qua nhưng vẫn đứng vững. Việc triển khai ngây thơ có thể chỉ cần bỏ qua các va chạm có nền tảng hướng xuống-> va chạm nhân vật bình thường (biểu thị đầu của người chơi chạm vào đáy của nền tảng), nhưng không có bộ nhớ đệm tiếp xúc, điều này sẽ bị phá vỡ nếu đầu của người chơi chọc qua nền tảng và sau đó anh ta bắt đầu ngã. Tại thời điểm đó, liên lạc bình thường có thể sẽ hướng lên trên, khiến người chơi bật lên thông qua nền tảng khi anh ta không nên. Với bộ nhớ đệm liên hệ, động cơ có thể nhìn vào sự va chạm ban đầu bình thường và bỏ qua tất cả các sự kiện liên hệ tiếp theo cho đến khi nền tảng và trình phát tách rời nhau một lần nữa.

Ngủ

Một kỹ thuật rất hữu ích khác là đánh dấu các đối tượng là "ngủ" nếu chúng không được tương tác. Các vật thể ngủ không được cập nhật vật lý, không va chạm với các vật thể ngủ khác và về cơ bản chỉ cần ngồi đó đông cứng kịp thời cho đến khi một vật thể không ngủ khác va chạm với chúng.

Tác động là tất cả các cặp đối tượng va chạm chỉ ngồi đó không làm gì mà không mất thời gian xử lý. Ngoài ra, vì không có số lượng hiệu chỉnh vật lý nhỏ liên tục, các ngăn xếp sẽ ổn định.

Một đối tượng là một ứng cử viên cho giấc ngủ khi nó có vận tốc gần như bằng không trong hơn một khung hình. Lưu ý rằng epsilon bạn sử dụng để kiểm tra vận tốc gần như bằng không này có thể sẽ cao hơn một chút so với epsilon so sánh điểm nổi thông thường, vì bạn sẽ mong đợi một số jitter với các đối tượng xếp chồng lên nhau và bạn muốn toàn bộ các đối tượng ngủ thiếp đi nếu chúng ngủ Đang ở "đủ gần" để ổn định. Ngưỡng tất nhiên sẽ yêu cầu điều chỉnh và thử nghiệm.

Những ràng buộc

Điểm chính cuối cùng của nhiều động cơ vật lý là bộ giải hạn chế. Mục đích của một hệ thống như vậy là để tạo thuận lợi cho việc thực hiện những thứ như lò xo, động cơ, trục bánh xe, thân mềm mô phỏng, vải, dây thừng và dây chuyền, và đôi khi cả chất lỏng (mặc dù chất lỏng thường được thực hiện như một hệ thống hoàn toàn khác).

Ngay cả những điều cơ bản của việc giải quyết ràng buộc cũng có thể trở nên rất chuyên sâu về toán học và vượt xa chuyên môn của tôi trong vấn đề này. Tôi khuyên bạn nên kiểm tra loạt bài viết xuất sắc về vật lý của Randy Gaul để có giải thích sâu hơn về chủ đề này.


nếu bạn sẽ giải quyết số lượng độ phân giải va chạm tối thiểu thì có lẽ bạn cũng nên giải quyết nhu cầu giữ số lượng càng thấp càng tốt vì trong một thiết lập phức tạp, cho phép số lần lặp va chạm cao sẽ làm giảm đáng kể tốc độ khung hình. sau đó khi bạn đang nói về số lần lặp là mỗi cặp hoặc là cho tất cả các va chạm.
vườn06

1
@ gardenian06: đó là một tổng quan nhanh chóng bằng văn bản, chắc chắn rằng nó có thể được mở rộng khá nhiều. tôi quên đề cập đến việc ngủ đối tượng, ví dụ, điều này khá hữu ích. đối với các lần lặp, tôi lặp lại tất cả các bộ sưu tập các cặp và thậm chí với số lần lặp tương đối lớn (20+) Tôi chưa bao giờ nhận thấy vấn đề về hiệu năng (nhưng một lần nữa, đó là với đối tượng đang ngủ, do đó, một số lượng va chạm hoạt động tương đối nhỏ để giải quyết ).
Sean Middleditch

1
Câu trả lời tuyệt vời, +1. Đọc điều này thực sự khiến tôi muốn thực hiện các thuật toán này.
Miles Rout

3

Vấn đề chung: xác định những sự kết hợp có thể có của các đối tượng có thể tích giao nhau khác không.

Cách tiếp cận chung, ngây thơ rất đơn giản: Đối với mỗi cặp đối tượng có thể, hãy tính thể tích giao nhau. Điều này thường không thực tế, vì nó đòi hỏi O (n ^ 2) các hoạt động giao nhau tương đối đắt tiền.

Do đó, việc triển khai thực tế thường là chuyên biệt, đưa ra các giả định nhất định để cho phép tránh việc kiểm tra giao nhau hoặc giảm chi phí. Phân vùng không gian lợi dụng thực tế là các đối tượng thường nhỏ so với tổng khối lượng và thường sẽ giảm số lượng so sánh với O (n log n). Các hộp giới hạn liên kết trục và các mặt cầu giới hạn cung cấp các kiểm tra giao nhau thô không tốn kém, miễn là các đối tượng tuân theo các giả định về độ nén nhất định. Và như vậy.


2

Một "động cơ va chạm" tôi đã sử dụng cảm thấy cực kỳ dễ nắm bắt.

Về cơ bản, API đã cung cấp một loại đối tượng có phương thức collidesWith, sao cho

  1. các tham số của nó là các loại đối tượng khác nhau "đủ điều kiện" để va chạm
  2. nó trả về đúng hay sai tùy thuộc vào việc va chạm có xảy ra hay không
  3. có một tùy chọn cho phép chọn xem tất cả các hình chữ nhật giới hạn cho sự kiện va chạm kích hoạt đối tượng hay chỉ các pixel mờ trong các hình chữ nhật này (phát hiện mức pixel)

Trong ứng dụng của mình, tôi chỉ định kỳ gọi collidesWithđể tìm hiểu xem có xảy ra va chạm hay không.

Khá đơn giản phải không?


Có lẽ điều duy nhất đòi hỏi một sự tưởng tượng nhỏ là khi hình chữ nhật giới hạn đơn giản không đủ để mô phỏng hình học của các vật thể va chạm. Trong trường hợp này, người ta chỉ cần sử dụng một số vật thể có thể thay thế thay vì một vật thể.

Nói chung, khi bạn phát hiện ra rằng hình chữ nhật va chạm đơn lẻ không làm những gì bạn cần, bạn phát minh ra cách phân tách mọi thứ thành các phần tử phụ hình chữ nhật hơn để khi kết hợp, các phần tử này mô phỏng / xấp xỉ hành vi mong muốn.

  • Người dùng cuối chỉ không quan tâm có bao nhiêu đối tượng đằng sau hậu trường. Họ hạnh phúc miễn là kết quả cuối cùng cảm thấy như họ mong đợi, ví dụ như một ngôi nhà có hàng rào sân sau xung quanh nó:

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


2

Tôi nghĩ rằng bạn có một chút bối rối về những gì bạn đang nói về, và đang nói về một vài điều khác nhau.

khả năng nói rằng vật phẩm này được di chuyển từ vị trí X đến vị trí Y dựa trên vật lý (điều này cũng tấn công cách chúng di chuyển và lý do chúng di chuyển)

phương pháp được sử dụng để phát hiện va chạm được xác định dựa trên cấu trúc trò chơi của bạn. nếu trò chơi của bạn là một thế giới mở rộng lớn thì bạn nên cân nhắc rất nhiều việc phân vùng không gian (quad-tree [oct-tree cho 3D], BSP, Grid truyền thống hoặc phương pháp thử nghiệm cũ theo mọi cách tiếp cận)

cách tốt nhất để thực hiện một hệ thống phát hiện va chạm là làm như vậy theo các bước.

  1. đặt tất cả các đối tượng vào một khối lượng / hình dạng giới hạn chung, và sau đó kiểm tra chúng

  2. nếu 1 vượt qua thì lặp lại với âm lượng / hình dạng phức tạp hơn lặp lại cho đến khi sẵn sàng kiểm tra hình học tuyệt đối

  3. kiểm tra hình học tuyệt đối số lượng thời gian bạn lặp lại bước 2 sẽ được xác định về độ phức tạp của các hình dạng của bạn và mức độ chính xác của các hình dạng đó.

bạn nên xem xét từng bước trong số các bước này sớm và nhằm mục đích loại bỏ va chạm khi bạn đi và chỉ trở về đúng ở bước 3 nếu chúng thực sự chạm vào.

Sau đó cho phần cuối cùng là giải quyết va chạm. điều này xác định những gì xảy ra sau khi bạn tìm thấy một vụ va chạm và đã chứng minh rằng đó thực sự là một vụ va chạm, và phải làm gì với nó. điều này thường được xử lý bởi vật lý.

vòng lặp truyền thống trông như thế này:

receive input
update physics
collision detection
collision resolution
render
repeat

Tôi chỉ muốn chỉ ra rằng rất hiếm khi các công cụ trò chơi sẽ thử nghiệm hình học tuyệt đối cho các va chạm. Thông thường thuật toán sẽ chỉ đi đến bước 2 trong phác thảo của bạn.
kevintodisco

Hầu hết các công cụ trò chơi kiểm tra hình học tuyệt đối trong nhiều trường hợp (không phải tất cả). Không làm như vậy sẽ có những "trục trặc" rất rõ ràng trong phản ứng vật lý. Hầu hết các động cơ sẽ có một pha rộng đơn giản (phân vùng không gian), kiểm tra âm lượng giới hạn đơn giản (phổ biến nhất là AABB), và sau đó (khi cần thiết) một thử nghiệm hình học đơn giản (ví dụ, không phải là hình học giống như hình học kết xuất LOD đầy đủ, nhưng vẫn là hình học thô có khả năng là một trong những phiên bản LOD thấp của lưới được kết xuất).
Sean Middleditch

@seanmiddleditch có ý định của tôi nhiều hơn là một phép tính gần đúng sẽ được kiểm tra thường cố gắng tránh kiểm tra đa giác lõm / đa diện.
vườn06

@ktodisco nó phụ thuộc vào độ chụm của hình và độ chính xác của nó, và sau đó cần phải trả lại gì cho hệ thống vật lý để giải quyết va chạm vì điều này có thể thay đổi dựa trên động cơ vật lý và độ chính xác dự định của phản hồi
vườn06

Giải thích của @ Guard06 seanmiddleditch khả thi hơn rất nhiều, mặc dù thử nghiệm cho các giao điểm tuyệt đối giữa các nhân vật được tạo thành từ hàng ngàn đa giác vẫn không phải là một ý tưởng hay.
kevintodisco

1

Ở cấp độ card đồ họa (nơi bạn thường xử lý các hình tam giác), ý tưởng chung là phân vùng cảnh của bạn theo một cách nào đó để bạn không phải kiểm tra tất cả N hình tam giác (điều này có thể được thực hiện như một bước xử lý trước ), và sau đó tìm ra vị trí của bạn trong cảnh và chỉ kiểm tra 10-50 hình tam giác trong phân vùng đó.

Xem cây BSP và Kd để biết thêm. Ngoài ra còn có các cách tiếp cận phân vùng khác.


0

Đầu tiên, tôi nghĩ rằng công việc quan trọng nhất của động cơ va chạm là xác định những gì không cần kiểm tra va chạm trong bất kỳ tình huống cụ thể nào trên khung theo khung và loại bỏ các đối tượng đó khỏi các kiểm tra tiếp theo.

Thứ hai, nhưng cũng rất quan trọng, hãy kiểm tra một cách chi tiết (chính xác) hơn đối với các đối tượng còn lại chưa được loại bỏ trong bước đầu tiên đó.

Thứ ba, sử dụng các phương pháp hiệu quả / phù hợp nhất để thực hiện kiểm tra.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.