Tạo thủ tục, cập nhật trò chơi và hiệu ứng cánh bướm


10

LƯU Ý: Tôi đã hỏi điều này trên Stack Overflow vài ngày trước nhưng có rất ít lượt xem và không có phản hồi. Hình tôi nên hỏi trên gamdev.stackexchange.

Đây là một câu hỏi / yêu cầu chung để được tư vấn về việc duy trì một hệ thống tạo thủ tục thông qua nhiều cập nhật sau phát hành, mà không phá vỡ nội dung được tạo trước đó.

Tôi đang cố gắng tìm thông tin và kỹ thuật để tránh các vấn đề "Hiệu ứng cánh bướm" khi tạo nội dung thủ tục cho các trò chơi. Khi sử dụng trình tạo số ngẫu nhiên có hạt, một chuỗi lặp ngẫu nhiên có thể được sử dụng để tạo ra một thế giới có thể tái tạo. Mặc dù một số trò chơi chỉ lưu thế giới được tạo vào đĩa sau khi được tạo, một trong những tính năng mạnh mẽ của việc tạo thủ tục là bạn có thể dựa vào khả năng tái tạo của chuỗi số để tạo lại một vùng nhiều lần theo cùng một cách, loại bỏ nhu cầu kiên trì. Do những hạn chế của tình huống cụ thể của tôi, tôi phải giảm thiểu sự kiên trì và cần phải dựa vào sự tập trung hoàn toàn hạt giống càng nhiều càng tốt.

Mối nguy hiểm chính trong phương pháp này là ngay cả sự thay đổi nhỏ nhất trong hệ thống tạo thủ tục cũng có thể gây ra hiệu ứng cánh bướm làm thay đổi toàn bộ thế giới. Điều này làm cho nó rất khó để cập nhật trò chơi mà không phá hủy thế giới mà người chơi đang khám phá.

Kỹ thuật chính mà tôi đã sử dụng để tránh vấn đề này là thiết kế việc tạo thủ tục theo nhiều giai đoạn, mỗi giai đoạn có trình tạo số ngẫu nhiên giống. Điều này có nghĩa là mỗi hệ thống phụ được khép kín và nếu một cái gì đó bị phá vỡ, nó sẽ không ảnh hưởng đến mọi thứ trên thế giới. Tuy nhiên, điều này có vẻ như vẫn có nhiều khả năng "phá vỡ", ngay cả khi trong một phần bị cô lập của trò chơi.

Một cách khác có thể xử lý vấn đề này có thể là duy trì các phiên bản hoàn chỉnh của trình tạo của bạn trong mã và tiếp tục sử dụng trình tạo đúng cho một thể hiện thế giới nhất định. Điều này có vẻ như là một cơn ác mộng bảo trì đối với tôi và tôi tò mò liệu có ai thực sự làm điều này không.

Vì vậy, câu hỏi của tôi thực sự là một yêu cầu cho lời khuyên, kỹ thuật và thiết kế chung - các mẫu thiết kế để xử lý vấn đề này về hiệu ứng cánh bướm, đặc biệt là trong bối cảnh cập nhật trò chơi sau khi phát hành. (Hy vọng đó không phải là một câu hỏi quá rộng.)

Tôi hiện đang làm việc trong Unity3D / C #, mặc dù đây là câu hỏi bất khả tri về ngôn ngữ.

CẬP NHẬT:

Cảm ơn vì câu trả lời của bạn.

Nó trông ngày càng giống dữ liệu tĩnh là cách tiếp cận tốt nhất và an toàn nhất, và cũng vậy, khi lưu trữ nhiều dữ liệu tĩnh không phải là một lựa chọn, có một chiến dịch dài trong một thế giới được tạo sẽ yêu cầu sử dụng phiên bản nghiêm ngặt của các máy phát. Lý do cho sự hạn chế trong trường hợp của tôi là nhu cầu lưu trữ / đồng bộ hóa trên nền tảng di động. Giải pháp của tôi có thể là tìm cách lưu trữ một lượng nhỏ dữ liệu nhỏ gọn về những thứ thiết yếu.

Tôi thấy khái niệm "Lồng" của Stormwind là một cách suy nghĩ đặc biệt hữu ích về mọi thứ. Một cái lồng về cơ bản là một điểm khởi động, ngăn chặn các hiệu ứng chạy dọc của những thay đổi nhỏ, tức là nhốt con bướm.


Tôi đang bỏ phiếu để đóng câu hỏi này ngoài chủ đề vì nó quá rộng.
Almo

Tôi nhận ra nó rất rộng. Bạn có đề nghị tôi thử một diễn đàn gamedev hoặc một cái gì đó thay thế? Thực sự không có cách nào để làm cho câu hỏi cụ thể hơn. Tôi đã hy vọng tôi có thể nghe được từ một người có nhiều kinh nghiệm trong lĩnh vực này, với một số mánh khóe xảo quyệt chưa xảy ra với tôi.
null

2
Almo bị nhầm. Nó không phải là rộng rãi. Đây là một câu hỏi xuất sắc và khá hẹp đủ để đưa ra câu trả lời tốt. Đó là điều mà tôi nghĩ rằng rất nhiều người trong chúng ta thường suy ngẫm.
Kỹ sư

Câu trả lời:


8

Tôi nghĩ rằng bạn đã bao gồm các căn cứ ở đây:

  • Sử dụng nhiều máy phát điện hoặc gieo lại hạt trong các khoảng thời gian (ví dụ: sử dụng băm không gian) để hạn chế sự lan tỏa từ các thay đổi. Điều này có thể hoạt động cho nội dung mỹ phẩm, nhưng như bạn chỉ ra nó vẫn có thể gây ra vỡ trong một phần.

  • Theo dõi phiên bản trình tạo được sử dụng trong tệp lưu và phản hồi phù hợp. "Thích hợp" nghĩa là gì ...

    • Giữ một lịch sử của tất cả các phiên bản trước của trình tạo trong trò chơi của bạn có thể thực hiện được và sử dụng bất kỳ phiên bản nào phù hợp với lưu. Điều này khiến việc sửa lỗi trở nên khó khăn hơn nếu người chơi tiếp tục sử dụng các bản lưu cũ.
    • Cảnh báo cho người chơi rằng tệp lưu này là từ một phiên bản cũ và cung cấp một liên kết để truy cập phiên bản đó dưới dạng thực thi riêng biệt. Tốt cho các trò chơi có chiến dịch kéo dài vài giờ đến vài ngày, tệ cho chiến dịch bạn mong đợi được chơi trong nhiều tuần trở lên.
    • Chỉ giữ lại các nphiên bản trình tạo cuối cùng trong tệp thực thi của bạn. Nếu tệp lưu sử dụng một trong những phiên bản gần đây, (đề nghị) cập nhật tệp lưu thành phiên bản mới nhất. Điều này sử dụng trình tạo thích hợp để giải nén bất kỳ trạng thái lỗi thời nào thành chữ (hoặc vào vùng đồng bằng từ đầu ra của trình tạo mới trên cùng một hạt giống, nếu chúng rất giống nhau). Bất kỳ trạng thái mới từ đây trở đi đến từ các máy phát điện mới nhất. Người chơi không chơi trong một thời gian dài có thể bị bỏ lại phía sau. Và trong trường hợp xấu nhất bạn sẽ lưu trữ toàn bộ trạng thái trò chơi ở dạng nghĩa đen, trong trường hợp đó bạn cũng có thể ...
  • Nếu bạn muốn thay đổi logic thế hệ của mình thường xuyên và không muốn phá vỡ tính tương thích với các phiên bản trước, đừng dựa vào tính xác định của trình tạo: lưu toàn bộ trạng thái của bạn trong tệp lưu của bạn. (tức là "Nuke nó từ quỹ đạo. Đó là cách duy nhất để chắc chắn")


Nếu bạn xây dựng các quy tắc thế hệ, vậy có cách nào để bạn đảo ngược thế hệ không? IE, được đưa ra một trạng thái trò chơi, bạn có thể hoàn nguyên nó thành một hạt giống không? Nếu có thể với dữ liệu của bạn, thay vì liên kết trình phát với phiên bản trò chơi khác, bạn có thể cung cấp tiện ích cập nhật tạo thế giới từ hạt giống với hệ thống cũ hơn, sau đó sử dụng trạng thái được tạo để tạo hạt giống cho trình tạo mới. Bạn có thể phải cảnh báo người chơi của bạn chờ đợi chuyển đổi mặc dù.
Joe

1
Điều này là không nói chung có thể. Bạn thậm chí không đảm bảo rằng có tồn tại một hạt giống cho trình tạo mới mang lại đầu ra giống như thế hệ cũ. Thông thường những hạt giống này chứa khoảng 64 bit, nhưng số thế giới có thể có mà trò chơi của bạn có thể hỗ trợ có thể lớn hơn 2 ^ 64, vì vậy mỗi trình tạo chỉ tạo ra một tập hợp con trong số này. Việc thay đổi trình tạo sẽ rất có thể dẫn đến một tập hợp con các cấp mới, có thể có ít hoặc thậm chí không có giao điểm với bộ của trình tạo trước đó.
DMGregory

Thật khó để chọn câu trả lời "Đúng". Tôi chọn cái này vì nó ngắn gọn và tóm tắt các vấn đề chính một cách rõ ràng. Cảm ơn.
null

4

Nguồn chính của Hiệu ứng Bướm như vậy được cho là không tạo ra số - đủ dễ để giữ tính xác định từ một trình tạo số duy nhất - mà là sử dụng các số đó theo mã máy khách. Thay đổi mã là thách thức thực sự trong việc giữ cho mọi thứ ổn định.

Mã: Bài kiểm tra đơn vị Cách tốt nhất để đảm bảo rằng một số thay đổi nhỏ ở đâu đó không biểu hiện ở nơi khác ngoài ý muốn, là bao gồm các thử nghiệm đơn vị kỹ lưỡng cho mọi khía cạnh tổng quát, trong bản dựng của bạn. Điều này đúng với bất kỳ đoạn mã nhỏ gọn nào trong đó việc thay đổi một thứ có thể ảnh hưởng đến nhiều thứ khác - bạn cần thử nghiệm cho tất cả để bạn có thể thấy trên một bản dựng duy nhất đã bị ảnh hưởng.

Số: Chuỗi / Slots định kỳ Giả sử bạn có một trình tạo số phục vụ cho mọi thứ. Nó không gán nghĩa, nó chỉ tạo ra các số theo thứ tự - giống như bất kỳ PRNG nào. Cho cùng một hạt giống trong hai lần chạy, chúng ta có được các chuỗi giống nhau, đúng không? Bây giờ bạn đưa ra một số suy nghĩ và quyết định rằng có thể có 30 khía cạnh của trò chơi của bạn sẽ thường xuyên cần được cung cấp với một giá trị ngẫu nhiên. Ở đây chúng tôi chỉ định một chuỗi chu kỳ gồm 30 vị trí, ví dụ: mỗi số đầu tiên trong chuỗi là bố cục địa hình gồ ghề, mỗi số thứ hai là nhiễu loạn địa hình ... vv ... mỗi số thứ 10 thêm một số lỗi cho trạng thái AI cho hiện thực. Vậy thời gian của bạn là 30.

Sau 10, bạn có 20 vị trí miễn phí mà bạn có thể sử dụng cho các khía cạnh khác khi tiến trình thiết kế trò chơi. Tất nhiên, chi phí ở đây là bạn phải tạo số cho các vị trí 11-30 mặc dù chúng hiện không được sử dụng , tức là hoàn thành giai đoạn, để quay lại chuỗi tiếp theo 1-10. Điều đó có chi phí CPU, mặc dù nó chỉ là nhỏ (tùy thuộc vào số lượng khe cắm miễn phí). Nhược điểm khác là bạn cần chắc chắn rằng thiết kế cuối cùng của bạn có thể được cung cấp theo số lượng vị trí bạn đã tạo sẵn khi bắt đầu quá trình phát triển của mình ... và bạn càng chỉ định khi bắt đầu, càng có nhiều vị trí "trống" bạn có khả năng phải trải qua từng thứ, để làm cho mọi thứ hoạt động.

Tác dụng của việc này là:

  • Bạn có một bộ tạo số cho tất cả mọi thứ
  • Thay đổi số lượng khía cạnh bạn cần để tạo số cho, sẽ không ảnh hưởng đến tính xác định (với điều kiện thời gian của bạn đủ lớn để đáp ứng tất cả các khía cạnh)

Tất nhiên, sẽ có một khoảng thời gian dài mà trò chơi của bạn không có sẵn cho công chúng - ở dạng alpha, có thể nói - để bạn có thể giảm từ 30 đến 20 khía cạnh mà không ảnh hưởng đến bất kỳ người chơi nào, chỉ mình bạn, nếu bạn nhận ra rằng bạn đã chỉ định cách quá nhiều vị trí khi bắt đầu. Điều này tất nhiên sẽ tiết kiệm một số chu kỳ CPU. Nhưng hãy nhớ rằng một hàm băm tốt (mà bạn có thể tự viết) nên nhanh như chớp. Vì vậy, phải chạy thêm khe cắm không nên tốn kém.


Chào. Nghe có vẻ giống với một số điều tôi đang làm. Tôi thường tạo ra một loạt các hạt giống phía trước dựa trên hạt giống thế giới ban đầu. Gần đây, tôi bắt đầu tạo ra một mảng nhiễu dài và sau đó mỗi "khe" chỉ đơn giản là một chỉ mục trong mảng đó. Bằng cách đó, mỗi hệ thống con có thể lấy đúng hạt giống và hoạt động độc lập. Một kỹ thuật tuyệt vời khác là sử dụng tọa độ x, y để tạo hạt giống cho từng vị trí. Tôi đang sử dụng mã từ câu trả lời của Euphoric trên trang ngăn xếp này: lập trình
null

3

Nếu bạn muốn kiên trì với PCG, tôi khuyên bạn nên coi chính mã PCG là dữ liệu . Giống như bạn sẽ duy trì dữ liệu qua các lần sửa đổi với nội dung thông thường, với nội dung được tạo, nếu bạn muốn duy trì dữ liệu đó qua các lần sửa đổi, bạn sẽ cần phải duy trì trình tạo.

Tất nhiên, cách tiếp cận phổ biến nhất là chuyển đổi dữ liệu được tạo thành dữ liệu tĩnh, như bạn đã đề cập.

Tôi không biết các ví dụ về các trò chơi có rất nhiều phiên bản máy phát điện, bởi vì tính bền bỉ là không bình thường trong các trò chơi PCG - đó là lý do tại sao mọi thứ thường đi đôi với PCG. Tuy nhiên, có rất nhiều ví dụ về nhiều PCG, thậm chí cùng loại, trong cùng một trò chơi. Ví dụ, Unangband có nhiều máy phát riêng biệt cho các phòng dungeon và khi thêm những cái mới, những cái cũ vẫn hoạt động như nhau. Cho dù đó là duy trì là tùy thuộc vào việc thực hiện của bạn. Một cách để duy trì nó là sử dụng các tập lệnh để triển khai các trình tạo của bạn, giữ chúng cách ly với phần còn lại của mã trò chơi.


Đó là một ý tưởng thông minh, chỉ đơn giản là sử dụng các máy phát khác nhau cho các khu vực khác nhau.
null

2

Tôi duy trì diện tích khoảng 30000 km2, giữ khoảng 1 triệu tòa nhà và các vật thể khác, ngoài các vị trí ngẫu nhiên của những thứ linh tinh. Một mô phỏng ngoài trời ofc. Dữ liệu được lưu trữ là ca 4 GB. Tôi may mắn có không gian lưu trữ, nhưng nó không giới hạn.

Ngẫu nhiên là ngẫu nhiên, không kiểm soát. Nhưng người ta có thể lồng nó một chút:

  • Kiểm soát nó bắt đầu kết thúc (như đã đề cập trong các bài viết khác, số hạt giống và số lượng số được tạo).
  • Giới hạn không gian số của nó, ví dụ. chỉ tạo các số nguyên từ 0 đến 100.
  • Bù đắp không gian số của nó, bằng cách thêm một giá trị (ví dụ: 100 + [số được tạo trong khoảng từ 0 đến 100] tạo ra các số ngẫu nhiên trong khoảng từ 100 đến 200)
  • Chia tỷ lệ cho nó (ví dụ: nhân với 0,1)
  • Và áp dụng các lồng khác nhau xung quanh nó. Đây là giảm, loại bỏ một phần của thế hệ. Ví dụ. nếu tạo trong không gian 2 chiều, người ta có thể đặt một hình chữ nhật lên trên các cặp số và loại bỏ những gì bên ngoài. Hoặc một hình tròn, hoặc một đa giác. Nếu trong không gian 3D, người ta có thể chấp nhận ví dụ chỉ các bộ ba cư trú bên trong một hình cầu hoặc một số hình dạng khác (hiện đang suy nghĩ trực quan, nhưng điều này không nhất thiết phải liên quan đến trực quan hóa hoặc định vị thực tế).

Đó là về nó. Lồng cũng tiêu thụ dữ liệu, thật không may.

Có một câu nói trong tiếng Phần Lan, Hajota ja hallitse. Dịch sang Phân chia và chinh phục .

Tôi nhanh chóng từ bỏ ý tưởng định nghĩa chính xác các chi tiết nhỏ nhất. Ngẫu nhiên muốn tự do, vì vậy nó có được tự do. Hãy để con bướm bay - bên trong lồng của nó. Thay vào đó tôi tập trung vào việc có một cách phong phú để xác định (và chính !!) các lồng. Không quan trọng chúng là những chiếc xe nào, miễn là chúng có màu xanh hoặc màu tối (một chủ nhân nhàm chán đã nói một lần :-)). "Blue hoặc darkblue" là cái lồng (rất nhỏ) ở đây, dọc theo chiều màu.

Điều gì có thể quản lý, để kiểm soát và quản lý không gian số?

  • Một lưới boolean là (bit nhỏ!)
  • Điểm góc là
  • Như là một cấu trúc cây (= để theo vào "lồng giữ lồng")

Bảo trì-khôn ngoan và phiên bản tương thích-khôn ngoan ... chúng ta có
: if version = n thì
: otherif version = m thì ...
Yep, cơ sở mã phát triển lớn hơn :-).

Những điều quen thuộc. Cách chính xác của bạn để đi trước sẽ imho là xác định một phương pháp phong phú để phân chia và chinh phục , và hy sinh một số dữ liệu về điều đó. Sau đó, nếu có thể, hãy cho tự do ngẫu nhiên (cục bộ), nơi không quan trọng để kiểm soát nó.

Không hoàn toàn không tương thích với "nuke it fom orbit" vui nhộn do DMGregory đề xuất, nhưng có lẽ sử dụng các hạt nhân nhỏ và chính xác? :-)


Cảm ơn câu trả lời của bạn. Nghe có vẻ như một khu vực thủ tục lớn ấn tượng để duy trì. Tôi có thể thấy làm thế nào cho một khu vực rộng lớn như vậy, ngay cả khi bạn có quyền truy cập vào nhiều bộ lưu trữ, vẫn không thể đơn giản là lưu trữ mọi thứ. Có vẻ như các máy phát điện phiên bản sẽ phải là con đường phía trước. Vậy là được :)
null

Trong tất cả các câu trả lời, tôi thấy mình suy nghĩ nhiều nhất về câu hỏi này. Tôi rất thích những mô tả hơi triết lý của bạn về mọi thứ. Tôi thấy thuật ngữ "Lồng" rất hữu ích khi giải thích các ý tưởng, vì vậy cảm ơn vì điều đó. Hãy để con bướm bay ... trong chuồng của nó :)
null

PS Tôi thực sự tò mò muốn biết bạn làm việc trên trò chơi nào. Bạn có thể chia sẻ thông tin đó?
null

Có thể thêm một điều nữa về không gian số: Thật đáng để luôn ở gần số không. Điều đó bạn có thể đã biết. Gần bằng 0 cho độ chính xác số tốt nhất và hầu hết tiếng nổ cho ít bit nhất. Bạn luôn có thể bù một loạt các số gần bằng 0 sau đó, nhưng bạn chỉ cần một số duy nhất cho số đó. Tương tự như vậy, bạn có thể (gần như nói rằng bạn PHẢI) di chuyển phép tính xa gần bằng 0, với phần bù. - Bão tố
Bão tố

Đánh giá trước đó, hãy xem xét chuyển động của xe nhỏ, mức tăng 1 khung hình là 0,01 [mét, đơn vị]: Bạn không thể tính chính xác 10000.1 + 0,01 với độ chính xác số 32 bit (đơn) nhưng bạn CÓ THỂ tính được 0,1 + 0,01. Do đó, nếu "hành động" diễn ra ở rất xa (phía sau những ngọn núi :-)), đừng đến đó, thay vào đó hãy di chuyển những ngọn núi về phía bạn (di chuyển với 10000, lúc đó bạn đang ở mức 0,1). Cũng hợp lệ cho không gian lưu trữ. Người ta có thể tham lam với việc lưu trữ các giá trị số gần nhau. Lưu trữ phần chung của chúng một lần và các biến thể riêng lẻ - có thể tiết kiệm bit! Bạn đã tìm thấy các liên kết? ;-)
Stormwind
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.