Làm thế nào tôi có thể thực hiện một mô phỏng vật lý xác định?


43

Tôi đang tạo ra một trò chơi vật lý liên quan đến các cơ thể cứng nhắc trong đó người chơi di chuyển các mảnh và các bộ phận để giải câu đố / bản đồ. Một khía cạnh cực kỳ quan trọng của trò chơi là khi người chơi bắt đầu mô phỏng, nó chạy giống nhau ở mọi nơi , bất kể hệ điều hành, bộ xử lý của họ, v.v ...

Có rất nhiều điều phức tạp và các mô phỏng có thể chạy trong một thời gian dài, vì vậy điều quan trọng là động cơ vật lý hoàn toàn có tính quyết định đối với các hoạt động của dấu phẩy động, nếu không, một giải pháp có thể xuất hiện để "giải quyết" trên máy của một người chơi và "Thất bại" trên cái khác.

Làm thế nào tôi có thể đạt được sự quyết định này trong trò chơi của tôi? Tôi sẵn sàng sử dụng nhiều khung và ngôn ngữ khác nhau, bao gồm Javascript, C ++, Java, Python và C #.

Tôi đã bị Box2D (C ++) cám dỗ cũng như các ngôn ngữ tương đương của nó trong các ngôn ngữ khác, vì nó có vẻ đáp ứng nhu cầu của tôi, nhưng nó thiếu tính xác định dấu phẩy động, đặc biệt là với các hàm lượng giác.

Tùy chọn tốt nhất tôi từng thấy cho đến nay là tương đương Java của Box2D (JBox2D). Nó dường như thực hiện một nỗ lực xác định điểm nổi bằng cách sử dụng StrictMaththay vì Mathcho nhiều hoạt động, nhưng không rõ liệu công cụ này có đảm bảo mọi thứ tôi cần hay không khi tôi chưa xây dựng trò chơi.

Có thể sử dụng hoặc sửa đổi một công cụ hiện có cho phù hợp với nhu cầu của tôi không? Hay tôi sẽ cần phải tự chế tạo một động cơ?

EDIT: Bỏ qua phần còn lại của bài đăng này nếu bạn không quan tâm tại sao ai đó cần chính xác như vậy. Các cá nhân trong các bình luận và câu trả lời dường như tin rằng tôi đang tìm kiếm thứ gì đó tôi không nên, và như vậy, tôi sẽ giải thích thêm về cách trò chơi này hoạt động.

Người chơi được đưa ra một câu đố hoặc cấp độ, trong đó có chướng ngại vật và mục tiêu. Ban đầu, một mô phỏng không chạy. Sau đó, họ có thể sử dụng các mảnh hoặc công cụ được cung cấp cho họ để xây dựng một máy. Khi họ nhấn bắt đầu, mô phỏng bắt đầu và họ không thể chỉnh sửa máy nữa. Nếu máy giải quyết bản đồ, người chơi đã đánh bại cấp độ. Nếu không, họ sẽ phải nhấn dừng, thay đổi máy của họ và thử lại.

Lý do mọi thứ cần phải có tính xác định là vì tôi dự định tạo mã sẽ ánh xạ mọi máy (một tập hợp các mảnh và công cụ cố gắng giải quyết một mức) thành tệp xml hoặc json bằng cách ghi lại từng vị trí, kích thước và xoay của từng mảnh. Sau đó, người chơi có thể chia sẻ các giải (được thể hiện bằng các tệp này) để họ có thể xác minh các giải, học hỏi lẫn nhau, tổ chức các cuộc thi, cộng tác, v.v ... Tất nhiên, hầu hết các giải, đặc biệt là đơn giản hoặc nhanh chóng những người, sẽ không bị ảnh hưởng bởi sự thiếu quyết đoán. Nhưng các thiết kế chậm hoặc phức tạp giải quyết các mức độ thực sự khó có thể, và đó là những thiết kế có thể sẽ là thứ thú vị và đáng để chia sẻ nhất.


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện . Nếu bạn nghĩ rằng bạn có giải pháp cho vấn đề, vui lòng xem xét việc đăng nó dưới dạng câu trả lời thay vì nhận xét - điều này giúp dễ dàng chỉnh sửa, đánh giá thông qua bỏ phiếu / đánh dấu được chấp nhận hoặc nhận xét trực tiếp về đề xuất đó để phản hồi thay vì dệt trả lời thành một chủ đề cuộc trò chuyện dài hơn.
DMGregory

Câu trả lời:


45

Về việc xử lý số dấu phẩy động theo cách xác định

Điểm nổi là xác định. Vâng, nó nên được. Nó phức tạp.

Có rất nhiều tài liệu về số dấu phẩy động:

Và làm thế nào họ có vấn đề:

Để trừu tượng. Ít nhất, trên một luồng duy nhất, các hoạt động tương tự, với cùng một dữ liệu, xảy ra theo cùng một thứ tự, nên có tính xác định. Vì vậy, chúng ta có thể bắt đầu bằng cách lo lắng về đầu vào và sắp xếp lại.


Một đầu vào như vậy gây ra vấn đề là thời gian.

Trước hết, bạn nên luôn luôn tính cùng một dấu thời gian. Tôi không nói là không đo thời gian, tôi đang nói rằng bạn sẽ không dành thời gian cho mô phỏng vật lý, bởi vì sự biến đổi theo thời gian là một nguồn gây nhiễu trong mô phỏng.

Tại sao bạn đo thời gian nếu bạn không chuyển nó sang mô phỏng vật lý? Bạn muốn đo thời gian đã trôi qua để biết khi nào nên gọi một bước mô phỏng và - giả sử bạn đang sử dụng giấc ngủ - bao nhiêu thời gian để ngủ.

Do vậy:

  • Đo thời gian: Có
  • Sử dụng thời gian trong mô phỏng: Không

Bây giờ, hướng dẫn sắp xếp lại.

Trình biên dịch có thể quyết định f * a + bgiống như b + f * avậy, tuy nhiên có thể có kết quả khác. Nó cũng có thể biên dịch thành fmadd hoặc có thể quyết định lấy nhiều dòng như thế xảy ra cùng nhau và viết chúng bằng SIMD , hoặc một số tối ưu hóa khác mà tôi không thể nghĩ ra ngay bây giờ. Và hãy nhớ rằng chúng tôi muốn các hoạt động tương tự xảy ra trên cùng một đơn đặt hàng, lý do là chúng tôi muốn kiểm soát những hoạt động xảy ra.

Và không, sử dụng gấp đôi sẽ không cứu bạn.

Bạn cần phải lo lắng về trình biên dịch và cấu hình của nó, đặc biệt là để đồng bộ hóa các số dấu phẩy động trên mạng. Bạn cần có được các bản dựng để đồng ý làm điều tương tự.

Có thể cho rằng, viết lắp ráp sẽ là lý tưởng. Bằng cách đó bạn quyết định thao tác để làm. Tuy nhiên, đó có thể là một vấn đề cho việc hỗ trợ nhiều nền tảng.

Do vậy:


Trường hợp cho số điểm cố định

Do cách thức nổi được thể hiện trong bộ nhớ, các giá trị lớn sẽ mất độ chính xác. Lý do là giữ cho các giá trị của bạn nhỏ (kẹp) giảm thiểu vấn đề. Do đó, không có tốc độ lớn và không có phòng lớn. Điều đó cũng có nghĩa là bạn có thể sử dụng vật lý rời rạc vì bạn ít có nguy cơ bị đào hầm.

Mặt khác, các lỗi nhỏ sẽ tích lũy. Vì vậy, cắt ngắn. Ý tôi là, chia tỷ lệ và chuyển thành một kiểu số nguyên. Bằng cách đó bạn biết không có gì là xây dựng. Sẽ có các hoạt động bạn có thể làm với loại số nguyên. Khi bạn cần quay lại điểm nổi, bạn bỏ và hoàn tác chia tỷ lệ.

Lưu ý tôi nói quy mô. Ý tưởng là 1 đơn vị thực sự sẽ được biểu diễn dưới dạng sức mạnh của hai (ví dụ 16384). Dù đó là gì, hãy biến nó thành một hằng số và sử dụng nó. Về cơ bản, bạn đang sử dụng nó như là số điểm cố định. Trong thực tế, nếu bạn có thể sử dụng số điểm cố định thích hợp từ một số thư viện đáng tin cậy tốt hơn nhiều.

Tôi đang nói cắt ngắn. Về vấn đề làm tròn, điều đó có nghĩa là bạn không thể tin tưởng vào chút cuối cùng của bất kỳ giá trị nào bạn nhận được sau khi chọn. Vì vậy, trước quy mô diễn viên để có được nhiều hơn một chút so với mức bạn cần và cắt ngắn nó sau đó.

Do vậy:

  • Giữ giá trị nhỏ: Có
  • Làm tròn cẩn thận: Có
  • Đã sửa số điểm khi có thể: Có

Đợi đã, tại sao bạn cần điểm nổi? Bạn có thể không làm việc chỉ với một loại số nguyên? Ô đúng rồi. Lượng giác và bức xạ. Bạn có thể tính toán các bảng cho lượng giác và độ phóng xạ và nướng chúng trong nguồn của bạn. Hoặc bạn có thể thực hiện các thuật toán được sử dụng để tính toán chúng với số dấu phẩy động, ngoại trừ sử dụng số điểm cố định thay thế. Có, bạn cần phải cân bằng bộ nhớ, hiệu suất và độ chính xác. Tuy nhiên, bạn có thể đứng ngoài số dấu phẩy động và duy trì tính quyết định.

Bạn có biết họ đã làm những thứ như vậy cho PlayStation gốc không? Hãy gặp con chó của tôi, các bản vá lỗi .

Nhân tiện, tôi không nói là không sử dụng dấu phẩy động cho đồ họa. Chỉ dành cho vật lý. Ý tôi là, chắc chắn, các vị trí sẽ phụ thuộc vào vật lý. Tuy nhiên, như bạn biết một máy va chạm không phải phù hợp với một mô hình. Chúng tôi không muốn xem kết quả cắt ngắn của các mô hình.

Do đó: SỬ DỤNG SỐ ĐIỂM CỐ ĐỊNH.


Để rõ ràng, nếu bạn có thể sử dụng trình biên dịch cho phép bạn chỉ định cách các điểm nổi hoạt động và điều đó là đủ cho bạn, thì bạn có thể làm điều đó. Đó không phải lúc nào cũng là một lựa chọn. Bên cạnh đó, chúng tôi đang làm điều này cho chủ nghĩa quyết định. Số điểm cố định không có nghĩa là không có lỗi, sau tất cả chúng có độ chính xác hạn chế.

Tôi không nghĩ rằng "số điểm cố định là khó" là một lý do tốt để không sử dụng chúng. Và nếu bạn muốn một lý do chính đáng để sử dụng chúng, đó là tính quyết định, đặc biệt là tính quyết định trên các nền tảng.


Xem thêm:


Phụ lục : Tôi đề nghị giữ cho kích thước của thế giới nhỏ. Như đã nói, cả OP ans Jibb Smart đều đưa ra quan điểm rằng việc di chuyển ra khỏi phao gốc có độ chính xác kém hơn. Điều đó sẽ có ảnh hưởng đến vật lý, một thứ sẽ được nhìn thấy sớm hơn nhiều so với rìa thế giới. Số điểm cố định, tốt, có độ chính xác cố định, chúng sẽ tốt như nhau (hoặc xấu, nếu bạn thích) ở mọi nơi. Điều này là tốt nếu chúng ta muốn chủ nghĩa quyết định. Tôi cũng muốn đề cập rằng cách chúng ta thường làm vật lý có đặc tính khuếch đại các biến thể nhỏ. Xem Hiệu ứng cánh bướm - Vật lý quyết định trong Máy tạo khối và Máy tạo hình không thể tin được .


Một cách khác để làm vật lý

Tôi đã suy nghĩ, lý do tại sao sai số nhỏ về độ chính xác trong các số dấu phẩy động được khuếch đại là bởi vì chúng ta đang thực hiện các bước lặp trên các số đó. Mỗi bước mô phỏng chúng tôi lấy kết quả của bước mô phỏng cuối cùng và thực hiện các công cụ trên chúng. Tích lũy lỗi ontop lỗi. Đó là hiệu ứng cánh bướm của bạn.

Tôi không nghĩ rằng chúng ta sẽ thấy một bản dựng bằng cách sử dụng một luồng trên cùng một máy mang lại đầu ra khác nhau cho cùng một đầu vào. Tuy nhiên, trên một máy khác, nó có thể, hoặc một bản dựng khác có thể.

Có một đối số để thử nghiệm ở đó. Nếu chúng tôi quyết định chính xác cách mọi thứ hoạt động và chúng tôi có thể kiểm tra phần cứng đích, chúng tôi không nên đưa ra các bản dựng có hành vi khác.


Tuy nhiên, cũng có một lập luận cho việc không làm việc ở xa mà tích lũy quá nhiều lỗi. Có lẽ đây là một cơ hội để làm vật lý theo một cách khác.

Như bạn có thể biết, có vật lý liên tục và rời rạc, cả hai đều hoạt động trên mức độ mỗi đối tượng sẽ tiến lên theo dấu thời gian. Tuy nhiên, vật lý liên tục có các phương tiện để tìm ra sự va chạm tức thời thay vì thăm dò các vật thể khác nhau có thể để xem liệu có xảy ra va chạm hay không.

Vì vậy, tôi đề xuất như sau: sử dụng các kỹ thuật vật lý liên tục để tìm ra khi nào sự va chạm tiếp theo của mỗi đối tượng sẽ xảy ra, với dấu thời gian lớn, lớn hơn nhiều so với một bước mô phỏng duy nhất. Sau đó, bạn thực hiện va chạm gần nhất ngay lập tức và tìm ra mọi thứ sẽ diễn ra ngay lập tức.

Vâng, đó là rất nhiều công việc của một bước mô phỏng duy nhất. Điều đó có nghĩa là mô phỏng sẽ không bắt đầu ngay lập tức ...

... Tuy nhiên, bạn có thể mô phỏng một vài bước mô phỏng tiếp theo mà không cần kiểm tra va chạm mỗi lần, bởi vì bạn đã biết khi nào xảy ra va chạm tiếp theo (hoặc không có va chạm nào xảy ra trong dấu thời gian lớn). Hơn nữa, các lỗi tích lũy trong mô phỏng đó là không liên quan vì một khi mô phỏng đạt đến dấu thời gian lớn, chúng ta chỉ cần đặt các vị trí mà chúng ta đã tính toán trước.

Bây giờ, chúng ta có thể sử dụng ngân sách thời gian mà chúng ta đã sử dụng để kiểm tra va chạm từng bước mô phỏng để tính toán va chạm tiếp theo sau khi chúng ta tìm thấy. Đó là chúng ta có thể mô phỏng trước bằng cách sử dụng dấu thời gian lớn. Giả sử một thế giới bị giới hạn phạm vi (điều này sẽ không hoạt động đối với các trò chơi lớn), nên có một hàng trạng thái trong tương lai cho mô phỏng, và sau đó mỗi khung hình bạn chỉ cần nội suy từ trạng thái cuối cùng sang trạng thái tiếp theo.


Tôi sẽ tranh luận để nội suy. Tuy nhiên, do có sự tăng tốc, chúng ta không thể đơn giản nội suy mọi thứ theo cùng một cách. Thay vào đó chúng ta cần nội suy có tính đến gia tốc của từng đối tượng. Đối với vấn đề đó, chúng tôi chỉ có thể cập nhật vị trí giống như cách chúng tôi thực hiện cho dấu thời gian lớn (điều đó cũng có nghĩa là nó ít bị lỗi hơn vì chúng tôi sẽ không sử dụng hai triển khai khác nhau cho cùng một chuyển động).


Lưu ý : Nếu chúng ta đang thực hiện các số dấu phẩy động này, cách tiếp cận này không giải quyết được vấn đề của các đối tượng có hành vi khác xa với nguồn gốc của chúng. Tuy nhiên, trong khi sự thật là độ chính xác bị mất đi càng xa khỏi nguồn gốc, thì điều đó vẫn mang tính quyết định. Trong thực tế, đó là lý do tại sao thậm chí không đưa nó lên ban đầu.


Phụ lục

Từ OP trong bình luận :

Ý tưởng là người chơi sẽ có thể lưu máy của họ ở một số định dạng (chẳng hạn như xml hoặc json), để vị trí và góc quay của từng mảnh được ghi lại. Tập tin xml hoặc json đó sau đó sẽ được sử dụng để tái tạo máy trên máy tính của người chơi khác.

Vì vậy, không có định dạng nhị phân, phải không? Điều đó có nghĩa là chúng ta cũng cần phải lo lắng bất cứ điều gì hay không các số dấu phẩy động được phục hồi khớp với bản gốc. Xem: Float Precision Revisited: Nine Digit Float Portability


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
Vaillancourt

2
Câu trả lời chính xác! Thêm 2 điểm có lợi cho điểm cố định: 1. điểm nổi sẽ hành xử khác hoặc gần hơn so với điểm gốc (nếu bạn có cùng câu đố ở một nơi khác), nhưng điểm cố định sẽ không; 2. điểm cố định thực sự có nhiều hơn chính xác hơn so với dấu chấm động cho hầu hết các phạm vi của nó - bạn có thể đạt được độ chính xác bằng cách sử dụng điểm cố định tốt
Jibb thông minh

Có thể mã hóa dữ liệu nhị phân trong cả hai base64phần tử XML & JSON . Đây không phải là một cách hiệu quả để thể hiện một lượng lớn dữ liệu như vậy, nhưng không đúng khi ngụ ý rằng chúng ngăn chặn việc sử dụng các biểu diễn nhị phân.
Pikalek

1
@Pikalek Tôi biết, OP đã hỏi tôi về nó trên các bình luận, tôi đã đề cập đến cơ sở 64 như một tùy chọn, trong số các tùy chọn khác, bao gồm hex, diễn giải lại dưới dạng int và sử dụng định dạng protobuf vì dù sao cũng không ai hiểu các tệp đó. ) con người có thể đọc được. Sau đó - tôi giả sử - một mod đã xóa các bình luận (không, nó không có trong cuộc trò chuyện được liên kết ở trên). Điều đó sẽ xảy ra một lần nữa? Tôi có nên loại bỏ nó khỏi câu trả lời? Tôi có nên làm cho nó dài hơn?
Theraot

@Theraot Ah, tôi có thể thấy tôi có thể diễn giải điều đó khác nhau như thế nào trong bối cảnh kể từ khi xóa bình luận. (FWIW, tôi đã đọc qua các cuộc trò chuyện về cả câu trả lời này & câu hỏi). Và ngay cả khi có một cách hiệu quả để mã hóa dữ liệu, vẫn có vấn đề lớn hơn là đảm bảo rằng nó có nghĩa tương tự trên các nền tảng. Với sự khuấy động, có lẽ tốt nhất là cứ để nguyên như vậy. Cảm ơn đã làm rõ!
Pikalek

6

Tôi làm việc cho một công ty sản xuất một trò chơi chiến lược thời gian thực nổi tiếng nhất định và tôi có thể nói với bạn rằng tính xác định điểm nổi là có thể.

Sử dụng các trình biên dịch khác nhau, hoặc cùng một trình biên dịch với các cài đặt khác nhau, hoặc thậm chí các phiên bản khác nhau của cùng một trình biên dịch, đều có thể phá vỡ tính xác định.

Nếu bạn cần chơi chéo giữa các nền tảng hoặc phiên bản trò chơi thì tôi nghĩ bạn sẽ cần phải cố định điểm - trò chơi chéo duy nhất có thể có mà tôi biết với điểm nổi, là giữa PC và XBox1, nhưng điều đó khá điên rồ.

Bạn sẽ cần tìm một công cụ vật lý hoàn toàn xác định hoặc lấy một công cụ nguồn mở và làm cho nó có tính quyết định hoặc cuộn động cơ của riêng bạn. Ngoài đỉnh đầu, tôi có cảm giác rằng Unity của tất cả mọi thứ đã thêm một động cơ vật lý xác định, nhưng tôi không chắc liệu nó chỉ mang tính quyết định trên cùng một máy hay tất cả các máy.

Nếu bạn định thử cuộn đồ của riêng mình, một vài điều có thể giúp:

  • Phao IEE754 mang tính quyết định nếu bạn không làm gì quá trái cây (google "IEE754 xác định" để biết thêm thông tin về những gì được hoặc không được bảo hiểm)
  • Bạn cần đảm bảo mọi khách hàng đều có chế độ làm tròn và độ chính xác được đặt giống hệt nhau (sử dụng controlfp để đặt)
  • Chế độ làm tròn và độ chính xác có thể được thay đổi bởi một số thư viện toán học nhất định, vì vậy nếu bạn đang sử dụng bất kỳ lib đóng nào, bạn có thể muốn kiểm tra chúng sau khi thực hiện cuộc gọi (một lần nữa sử dụng controlfp để kiểm tra)
  • Một số hướng dẫn SIMD mang tính quyết định, rất nhiều không, hãy cẩn thận
  • như đã đề cập ở trên, để đảm bảo tính xác định, bạn cũng cần cùng một nền tảng, cùng một phiên bản chính xác của cùng một trình biên dịch, biên dịch cùng một cấu hình, với cùng các cài đặt trình biên dịch
  • xây dựng một số công cụ để phát hiện các desyncs trạng thái và giúp chẩn đoán chúng - ví dụ CRC trạng thái trò chơi mọi khung hình để phát hiện khi desync xảy ra, sau đó có chế độ ghi nhật ký dài, bạn có thể cho phép sửa đổi trạng thái trò chơi được ghi nhật ký vào tệp, sau đó lấy 2 tệp từ các mô phỏng được tách ra từ nhau và so sánh trong một công cụ khác để xem nó sai ở đâu
  • khởi tạo tất cả các biến của bạn trong trạng thái trò chơi, nguồn gốc của desyncs
  • toàn bộ quá trình mô phỏng trò chơi cần diễn ra theo cùng một thứ tự mỗi lần để tránh các desyncs, thật dễ dàng để hiểu sai điều này, nên cấu trúc mô phỏng trò chơi của bạn theo cách giảm thiểu điều này. Tôi thực sự không phải là một người mẫu thiết kế phần mềm, nhưng trong trường hợp này có lẽ đó là một ý tưởng tốt - bạn có thể xem xét một số mẫu mà mô phỏng trò chơi giống như một hộp an toàn và cách duy nhất để thay đổi trạng thái trò chơi là chèn "tin nhắn" hoặc "lệnh", chỉ có quyền truy cập const được cung cấp cho bất kỳ thứ gì bên ngoài trạng thái trò chơi (ví dụ: kết xuất, kết nối mạng, v.v.). Vì vậy, kết nối mạng mô phỏng cho trò chơi nhiều người chơi là trường hợp gửi các lệnh này qua mạng hoặc phát lại mô phỏng tương tự là trường hợp ghi lại luồng lệnh lần đầu tiên,

1
Unity thực sự đang hướng tới mục tiêu xác định đa nền tảng với hệ thống Vật lý Unity mới của họ cho Ngăn xếp công nghệ hướng dữ liệu của họ, nhưng theo tôi hiểu, nó vẫn đang trong quá trình hoàn thiện và chưa hoàn thành / sẵn sàng sử dụng.
DMGregory

Một ví dụ về một hướng dẫn SIMD không xác định là gì? Bạn đang nghĩ về những người gần đúng như thế rsqrtpsnào?
Ruslan

@DMGregory nó phải ở trong bản xem trước, vì bạn đã có thể sử dụng nó - nhưng như bạn nói nó có thể chưa được hoàn thành.
Joe

@Ruslan có rsqrtps / RCpps kết quả phụ thuộc vào việc triển khai
Joe

5

Tôi không chắc đây có phải là loại câu trả lời mà bạn đang tìm kiếm hay không, nhưng một cách khác có thể là chạy các phép tính trên một máy chủ trung tâm. Yêu cầu khách hàng gửi cấu hình đến máy chủ của bạn, để nó thực hiện mô phỏng (hoặc truy xuất bộ nhớ cache) và gửi lại kết quả, sau đó được máy khách diễn giải và xử lý thành đồ họa.

Tất nhiên, điều này sẽ tắt mọi kế hoạch mà bạn có thể phải chạy máy khách ở chế độ ngoại tuyến và tùy thuộc vào mức độ mô phỏng tính toán chuyên sâu mà bạn có thể cần một máy chủ rất mạnh. Hoặc nhiều cái, nhưng ít nhất bạn có tùy chọn để đảm bảo chúng có cùng cấu hình phần cứng và phần mềm. Một mô phỏng thời gian thực có thể khó nhưng không phải là không thể (nghĩ về các luồng video trực tiếp - chúng hoạt động, nhưng với một chút chậm trễ).


1
Tôi hoàn toàn đồng ý. Đây là cách bạn đảm bảo trải nghiệm được chia sẻ với tất cả người dùng. gamedev.stackexchange.com/questions/6645/ Loại sắp thảo luận về một chủ đề tương tự, so sánh sự khác biệt giữa phía khách hàng và vật lý phía máy chủ.
Tim Holt

1

Tôi sẽ đưa ra một gợi ý phản trực quan rằng, mặc dù không đáng tin cậy 100%, nên hoạt động tốt hầu hết thời gian và rất dễ thực hiện.

Giảm độ chính xác.

Sử dụng kích thước bước thời gian không đổi được xác định trước, thực hiện vật lý qua từng bước thời gian trong độ nổi chính xác kép tiêu chuẩn, nhưng sau đó định lượng độ phân giải của tất cả các biến thành độ chính xác đơn (hoặc thậm chí tệ hơn) sau mỗi bước. Sau đó, hầu hết các sai lệch có thể có mà sắp xếp lại dấu phẩy động có thể đưa ra (so với một lần chạy tham chiếu của cùng một chương trình) sẽ được loại bỏ vì những sai lệch đó xảy ra ở các chữ số thậm chí không tồn tại trong độ chính xác giảm. Do đó, độ lệch không có cơ hội tích tụ Lyapunov (Hiệu ứng cánh bướm) cuối cùng sẽ trở nên đáng chú ý.

Tất nhiên, mô phỏng sẽ kém chính xác hơn một chút (so với vật lý thực tế), nhưng điều đó không thực sự đáng chú ý miễn là tất cả các chương trình của bạn chạy đều không chính xác theo cùng một cách .

Bây giờ, về mặt kỹ thuật, tất nhiên có khả năng việc sắp xếp lại sẽ gây ra độ lệch đạt đến một chữ số có ý nghĩa cao hơn, nhưng nếu độ lệch thực sự chỉ gây ra và giá trị của bạn đại diện cho các đại lượng vật lý liên tục, thì điều này cực kỳ khó xảy ra. Lưu ý rằng có nửa tỷ doublegiá trị giữa hai giá trị bất kỳ single, vì vậy phần lớn các bước thời gian trong hầu hết các mô phỏng có thể được dự kiến ​​là giống hệt nhau giữa các lần chạy mô phỏng. Một số ít trường hợp sai lệch thực hiện thông qua định lượng sẽ hy vọng sẽ được mô phỏng trong thời gian dài (ít nhất là không phải với động lực hỗn loạn).


Tôi cũng khuyên bạn nên xem xét cách tiếp cận hoàn toàn ngược lại với những gì bạn đang hỏi về: nắm lấy sự không chắc chắn ! Nếu hành vi hơi không đặc biệt, thì điều này thực sự gần với các thí nghiệm vật lý thực tế. Vì vậy, tại sao không cố tình chọn ngẫu nhiên các tham số khởi đầu cho mỗi lần chạy mô phỏng và yêu cầu mô phỏng thành công nhất quán qua nhiều thử nghiệm? Điều đó sẽ dạy nhiều hơn về vật lý và về cách chế tạo các máy móc đủ mạnh / tuyến tính, thay vì siêu mỏng manh chỉ thực tế trong một mô phỏng.


Làm tròn xuống sẽ không có ích, bởi vì nếu kết quả có độ chính xác cao là không xác định thì cuối cùng kết quả sẽ làm tròn một chiều trên một hệ thống và cách khác trên một hệ thống khác. Ví dụ: bạn luôn có thể làm tròn đến số nguyên gần nhất, nhưng sau đó một máy tính hệ thống 1.0 và máy tính khác tính toán 0.9999999999999999999999999999999999999999 và chúng làm tròn khác nhau.
yoyo

Vâng, điều đó là có thể, như tôi đã nói trong câu trả lời. Nhưng nó sẽ xảy ra cực kỳ hiếm khi xảy ra , cũng như các trục trặc khác trong vật lý trò chơi. Vì vậy, làm tròn không giúp đỡ. (Tuy nhiên, tôi sẽ không làm tròn xuống ; làm tròn đến gần nhất để tránh
sai lệch

0

Tạo lớp của riêng bạn để lưu trữ số!

Bạn có thể buộc một hành vi xác định nếu bạn biết chính xác cách tính toán sẽ được thực hiện. Ví dụ: nếu các thao tác duy nhất bạn xử lý là nhân, chia, cộng và trừ, thì nó sẽ đủ để biểu diễn tất cả các số chỉ là một số hữu tỷ. Để làm điều này, một lớp Rational đơn giản sẽ làm tốt.

Nhưng nếu bạn muốn xử lý các tính toán phức tạp hơn (ví dụ có thể là các hàm lượng giác), thì bạn sẽ phải tự viết các hàm đó. Nếu bạn muốn có thể lấy sin của một số, bạn sẽ phải viết một hàm gần đúng với sin của một số trong khi chỉ sử dụng các thao tác được đề cập ở trên. Đây là tất cả có thể làm được, và theo ý kiến ​​của tôi, nó cắt bỏ phần lớn các chi tiết lông trong các câu trả lời khác. Sự đánh đổi là thay vào đó bạn sẽ phải đối phó với một số toán học.


3
Số học hợp lý hoàn toàn không thể thực hiện được đối với bất kỳ loại tích hợp số nào. Ngay cả khi mỗi bước thời gian chỉ thực hiện * / + -thì mẫu số sẽ ngày càng lớn hơn theo thời gian.
leftaroundabout

Tôi hy vọng rằng ngay cả khi không xem xét tích hợp, đây sẽ không phải là một giải pháp tốt bởi vì chỉ sau một vài lần nhân hoặc chia, các số đại diện cho tử số và mẫu số của bạn sẽ tràn ra một số nguyên 64 bit.
jvn91173

0

Có một số nhầm lẫn về thuật ngữ ở đây. Một hệ thống vật lý có thể hoàn toàn xác định, nhưng không thể mô hình hóa trong một khoảng thời gian hữu ích vì hành vi của nó cực kỳ nhạy cảm với các điều kiện ban đầu và một thay đổi nhỏ vô cùng trong các điều kiện ban đầu sẽ tạo ra các hành vi hoàn toàn khác nhau.

Đây là video về một thiết bị thực có hành vi cố ý không thể đoán trước, ngoại trừ theo nghĩa thống kê:

https://www.youtube.com/watch?v=EvHiee7gs9Y

Thật dễ dàng để xây dựng các hệ thống toán học đơn giản (chỉ sử dụng phép cộng và phép nhân) trong đó kết quả sau N bước phụ thuộc vào vị trí thập phân thứ N của các điều kiện bắt đầu. Viết phần mềm để mô hình hóa một hệ thống như vậy một cách nhất quán, trên bất kỳ phần cứng và phần mềm máy tính nào mà người dùng có thể có, gần như không thể - ngay cả khi bạn có ngân sách đủ lớn để kiểm tra ứng dụng trên mọi sự kết hợp giữa phần cứng và phần mềm.

Cách tốt nhất để khắc phục điều này là tấn công vấn đề tại nguồn của nó: làm cho tính chất vật lý của trò chơi của bạn mang tính quyết định vì nó cần phải có được kết quả có thể lặp lại.

Cách khác là cố gắng làm cho nó có tính quyết định bằng cách điều chỉnh phần mềm máy tính để mô hình hóa một cái gì đó không phải là vật lý được chỉ định. Vấn đề là bạn đã đưa thêm một số lớp phức tạp vào hệ thống, so với việc thay đổi rõ ràng vật lý.

Như một ví dụ cụ thể, giả sử trò chơi của bạn liên quan đến sự va chạm của các cơ thể cứng nhắc. Ngay cả khi bạn bỏ qua ma sát, việc mô hình hóa chính xác các va chạm giữa các vật thể có hình dạng tùy ý có thể quay khi chúng di chuyển là không thể. Nhưng nếu bạn thay đổi tình huống để các đối tượng duy nhất là những viên gạch hình chữ nhật không quay, cuộc sống sẽ đơn giản hơn rất nhiều. Nếu các vật thể trong trò chơi của bạn trông không giống như những viên gạch, thì hãy che giấu sự thật đó bằng một số đồ họa "phi vật lý" - ví dụ, theo nghĩa đen là che giấu sự va chạm đằng sau một số khói hoặc lửa, hoặc một bong bóng văn bản hoạt hình "Ouch" hay bất cứ cái gì.

Người chơi phải khám phá vật lý trò chơi bằng cách chơi trò chơi. Sẽ không có vấn đề gì nếu nó không "hoàn toàn thực tế" miễn là nó tự nhất quán và đủ tương tự với trải nghiệm thông thường là hợp lý.

Nếu bạn làm cho vật lý tự hoạt động một cách ổn định, một mô hình máy tính của nó cũng có thể tạo ra kết quả ổn định, ít nhất là theo nghĩa các lỗi làm tròn sẽ không liên quan.


1
Tôi không thấy bất kỳ sự nhầm lẫn trong thuật ngữ. OP muốn hành vi xác định từ một hệ thống có khả năng hỗn loạn. Điều đó hoàn toàn có thể làm được.
Đánh dấu

Sử dụng các hình đơn giản hơn (như hình tròn và hình chữ nhật) hoàn toàn không thay đổi vấn đề. Bạn vẫn cần rất nhiều hàm lượng giác, sqrt, v.v ...
jvn91173

-1

Sử dụng độ chính xác của dấu phẩy động kép , thay vì độ chính xác của dấu phẩy động đơn . Mặc dù không hoàn hảo, nhưng nó đủ chính xác để được coi là tính quyết định trong vật lý của bạn. Bạn có thể gửi một tên lửa lên mặt trăng với độ chính xác điểm nổi gấp đôi, nhưng không phải là độ chính xác điểm nổi đơn.

Nếu bạn thực sự cần tính xác định hoàn hảo, hãy sử dụng toán điểm cố định . Điều này sẽ cung cấp cho bạn ít độ chính xác hơn (giả sử bạn sử dụng cùng số bit), nhưng kết quả xác định. Tôi không biết về bất kỳ động cơ vật lý nào sử dụng toán học điểm cố định, vì vậy bạn có thể cần phải tự viết nếu bạn muốn đi theo con đường này. (Một cái gì đó tôi sẽ khuyên chống lại.)


11
Cách tiếp cận chính xác kép chạy afoul của hiệu ứng cánh bướm . Trong một hệ thống động lực (như một sim vật lý), ngay cả một sai lệch nhỏ trong điều kiện ban đầu cũng có thể khuếch đại thông qua phản hồi, ném tuyết đến một lỗi có thể nhận thấy. Tất cả các chữ số phụ làm là trì hoãn điều này lâu hơn một chút - buộc quả cầu tuyết phải lăn xa hơn một chút trước khi nó đủ lớn để gây ra sự cố.
DMGregory

2
Hai sai lầm cùng một lúc: 1) Các điểm nổi kép chịu cùng một vấn đề và thường chỉ hoãn lại vấn đề thành một tương lai khó khăn hơn để gỡ lỗi trong tương lai. 2) Không có quy tắc nào quy định rằng điểm cố định phải kém chính xác hơn điểm nổi. Tùy thuộc vào tỷ lệ và vấn đề hiện tại hoặc trên bộ nhớ bạn đã sẵn sàng sử dụng cho mỗi số điểm cố định, chúng có thể kém chính xác hơn, chính xác như nhau hoặc chính xác hơn. Không có nghĩa gì để nói "họ ít chính xác hơn".
phresnel

@phresnel, như một ví dụ về độ chính xác điểm cố định, sê-ri IBM 1400 đã sử dụng toán học thập phân điểm cố định chính xác tùy ý. Dành 624 chữ số cho mỗi số và bạn đã vượt quá phạm vi độ chính xác của điểm nổi chính xác kép.
Đánh dấu

@phresnel (2) Điểm tốt. Tôi đã cập nhật câu trả lời của mình để giả sử cùng số bit.
Evorlor

-2

Sử dụng mẫu Memento .

Trong lần chạy đầu tiên của bạn, hãy lưu dữ liệu vị trí từng khung hoặc bất kỳ điểm chuẩn nào bạn cần. Nếu đó là quá không phù hợp, chỉ làm điều đó mỗi n khung.

Sau đó, khi bạn tái tạo mô phỏng, hãy làm theo vật lý tùy ý, nhưng cập nhật dữ liệu vị trí trên mỗi n khung.

Mã giả quá đơn giản:

function Update():
    if(firstRun) then (SaveData(frame, position));
    else if(reproducedRun) then (this.position = GetData(frame));

9
Tôi không nghĩ rằng điều này làm việc cho trường hợp của OP. Giả sử bạn và tôi đều chơi game trên các hệ thống khác nhau. Mỗi người trong chúng ta đặt các mảnh ghép theo cùng một cách - một giải pháp không được nhà phát triển dự đoán trước. Khi bạn nhấp vào "bắt đầu", PC của bạn sẽ mô phỏng vật lý sao cho giải pháp thành công. Khi tôi làm tương tự, một số khác biệt nhỏ trong mô phỏng dẫn đến giải pháp (giống hệt) của tôi không được xếp loại là thành công. Ở đây, tôi không có cơ hội tham khảo ý kiến ​​từ lần chạy thành công của bạn, bởi vì nó đã xảy ra trên máy của bạn chứ không phải vào thời điểm phát triển.
DMGregory

@DMGregory Đúng vậy. Cảm ơn bạn.
jvn91173
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.