'Khoanh vùng' lên các khu vực trên bản đồ gạch lớn, cũng như ngục tối


10

Trò chơi của tôi có một bản đồ giống như Minecraft, theo cách nó được tạo ngẫu nhiên và được tạo ngẫu nhiên. Và lớn. Giả sử người dùng đã khám phá vùng 1000x1000 (2D tại đây), vì vậy đó là 1.000.000 ô.

Rõ ràng là tôi sẽ không thể lưu trữ tất cả trong bộ nhớ. Tôi cũng không muốn bỏ qua mọi thứ trong 10 ô hoặc bất kỳ bán kính nào - cả hai sẽ không có gì cập nhật (tất cả các NPC, có lẽ là gạch phản ứng) và tôi sẽ phải làm việc với các vị trí khó xử như 1382.12918.

Vì vậy, nếu tôi chia nó thành các khối hoặc vùng hoặc bất cứ thứ gì nói là gạch 64x64, tôi sẽ phải lưu trữ từng vị trí của từng ô và đối tượng như:

Chunk a, b. Vị trí x, y.

Nhưng nếu tôi muốn ngục tối và những thứ tương tự trong bản đồ thì sao? Vì vậy, một ô duy nhất dẫn đến có thể là một hầm ngục 40 tầng, mỗi tầng có diện tích 40x40. Tôi không thể lưu trữ chính xác những người trong cùng một bản đồ.

Và có mặt ký ức; Tôi có thể lưu trữ bao nhiêu trong bộ nhớ cùng một lúc một cách hợp lý? Tôi có thể thực hiện các ô bằng ID khá dễ dàng và có mảng 2D bình thường ở đó. Hoặc một lần nữa, có một giải pháp hiệu quả hơn là có một tệp dữ liệu của các loại gạch ? Vì vậy, đối với 64x64..chỉ là 20K hoặc bất cứ điều gì. Tôi muốn càng nhiều càng tốt xung quanh để được tải về để cập nhật thực tế nhất. Nhưng tôi không biết mình có thể đạt được những giới hạn nào mà không bị nghẹt bộ nhớ.

Câu trả lời:


9

Mặc dù tôi đồng ý với tình cảm: "đừng lo lắng về điều đó trừ khi đó là vấn đề đã được chứng minh", tôi nghĩ rằng đáng để suy nghĩ về việc sớm: lắp giải pháp trở nên đau đớn hơn nhiều. Và vâng, chỉ cập nhật gạch 'gần đó' là cách họ sẽ đi. Nhưng lưu trữ và địa chỉ của các mục trong thế giới trò chơi của bạn một cách hiệu quả là rất quan trọng vì lý do hiệu suất.

Điều bạn thực sự nghĩ đến ở đây là một tập dữ liệu thưa thớt: thứ gì đó mà các chỉ mục tiềm năng lớn (hoặc không giới hạn), nhưng chỉ một tỷ lệ nhỏ thực sự được sử dụng. Điểm mấu chốt là bạn không biết chính xác tỷ lệ nào sẽ được sử dụng.

Giải pháp chuẩn cho một vấn đề tập dữ liệu thưa thớt là tách chỉ mục / địa chỉ khỏi lưu trữ dữ liệu thực tế. Vì vậy, nếu đối tượng gạch đắt tiền, thì lưu trữ nó ở dạng nhỏ gọn (ví dụ: một mảng phẳng). Nhưng cho phép nó được lập chỉ mục thông qua một đối tượng rẻ hơn. Ở dạng đơn giản nhất, đây có thể là ma trận 2D (hoặc 3D) mà bạn có thể dễ dàng lập chỉ mục theo tọa độ, nhưng mỗi mục trong ma trận chỉ đơn giản là một chỉ mục. Sau đó, bạn sử dụng chỉ mục đó để tra cứu nội dung ô thực tế trong một mảng nhỏ gọn, riêng biệt. Nếu nội dung ô chưa tồn tại, sau đó thêm chúng vào cuối mảng và lưu chỉ mục trong ma trận 3D.

Giải pháp trở nên phức tạp hơn nếu bạn muốn hỗ trợ xóa nội dung (vì nó dẫn đến sự phân mảnh của mảng nội dung) và nếu nội dung ô của bạn rẻ, thì trọng số thêm của chỉ mục (chỉ số 32 bit hoặc 64 bit) có thể sẽ áp đảo các khoản tiết kiệm từ việc không lưu trữ từng ô tiềm năng. Đây cũng là một tra cứu bổ sung, điều này sẽ làm giảm hiệu suất bộ nhớ cache của bạn.

Bạn có thể nhận được nhiều hiệu quả lưu trữ hơn bằng cách giới thiệu thêm các lớp cảm ứng. Giả sử bạn sắp xếp các ô của mình thành các khối và các khối có độ chi tiết là 64x64x64. Cho một ô ở 125, 1, 132, bạn biết nó thuộc chunk (1,0,2). Vì vậy, bạn có một thế giới, bao gồm một mảng chunk nhỏ gọn và một ma trận các chỉ số chunk (-1 nếu chunk không tồn tại). Nội dung của mỗi khối (nếu có) là một ma trận 64x64x64 của các chỉ số gạch (-1 nếu gạch chưa tồn tại) và một mảng nhỏ của các ô được sử dụng. Bằng cách này, bạn không đốt một lượng lớn các chỉ số gạch cho các khối không bao giờ được sử dụng. Bằng cách làm theo cách tiếp cận này và chọn các số hợp lý cho độ chi tiết khối, bạn có thể mở rộng quy mô vũ trụ của mình một cách ồ ạt và kiểm soát việc sử dụng bộ nhớ của bạn. Trên thực tế, nếu bạn tạo khối 32x32x32,

Bạn cũng có thể thực hiện các thủ thuật lén lút, như sử dụng bit thứ tự cao của các chỉ số chunk hoặc gạch của bạn để có nghĩa là một cái gì đó đặc biệt. Vì vậy, nếu một mục trong ma trận ô có tập bit trên cùng, thì 31 bit thấp hơn không có nghĩa là chỉ mục ô, thay vào đó chúng có nghĩa là 'chỉ số dọc' hoặc một cái gì đó tương tự, và bạn có thể tra cứu nó trong một danh sách được duy trì riêng để tìm ra tọa độ nó dẫn đến.


Tôi cảnh báo bất cứ ai gặp phải câu hỏi này trong tương lai: Mặc dù không có gì trong bài viết này là không chính xác, nhưng thật sự kinh khủng đối với một trò chơi như Minecraft, có một thế giới không thưa thớt. (Và MrCranky nói càng nhiều.) Thế giới của bạn chỉ được hưởng lợi từ điều này nếu nó có một vài điều và rất nhiều điều đáng chú ý , không phải là một vài điều và rất nhiều sự trống rỗng .

1
Tôi chân thành đồng ý rằng chi phí liên quan đến việc duy trì một giải pháp lưu trữ tập dữ liệu thưa thớt là khá cao, vì vậy bạn sẽ chỉ thực hiện nếu số dư rõ ràng bị lệch về phía thưa thớt. Các yếu tố chính ở đây là: chi phí của dữ liệu-mục và xác suất-dữ liệu-mục-không được sử dụng. Minecraft có một bộ dữ liệu tiềm năng lớn, đồ sộ (một số lượng lớn gạch theo mỗi hướng). Tỷ lệ thực tế của thế giới trò chơi tiềm năng được sử dụng là rất nhỏ. Mặc dù bạn yêu cầu một lượng lớn nó khi bạn di chuyển khắp thế giới, nó vẫn chỉ là một phần rất nhỏ của các mục dữ liệu tiềm năng.
MrCranky

1
Điều làm cho Minecraft khác biệt là chi phí cho mỗi đơn vị là rất nhỏ - đó có thể là một byte lưu trữ duy nhất? Một giá trị biểu thị 'không có gì ở đó', phần còn lại là các loại khối và bạn có thể dễ dàng điều chỉnh giá trị đó trong một byte. Vì vậy, bạn sẽ không có một chỉ mục cho một khối, điều đó thật điên rồ, chỉ mục này lớn hơn nhiều so với việc chỉ lưu trữ giá trị khối thực tế. Nhưng các quy tắc tập dữ liệu thưa thớt vẫn hoạt động ở các cấp cao hơn. Mỗi khối (ví dụ 64x64x64) rất tốn kém để lưu trữ (khối 256K), vì vậy nếu bạn có thể sử dụng một giá trị nhỏ duy nhất để biểu thị sự vắng mặt hoặc địa chỉ của nó nếu nó tồn tại, thì bạn đã lưu trữ dung lượng lớn.
MrCranky

6

Tại sao bạn không thể lưu trữ một triệu gạch trong bộ nhớ? Ngay cả điện thoại của tôi có RAM 256 MB; một triệu gạch trống sẽ là gì, 4-32MB?


Nó chỉ có vẻ như một số lượng lớn để được lưu trữ. Cùng với đó, sẽ mất nhiều thời gian để cập nhật chúng.
Vịt Cộng sản

2
Việc bỏ qua một tập hợp các bản cập nhật sẽ dễ dàng hơn nhiều so với việc xử lý một số loại giải pháp phân trang đĩa. Chỉ cần .. bỏ qua chúng. Đừng cập nhật các ô nhiều hơn khoảng cách X từ một diễn viên đã biết.

2
@TheCransistDuck Điều duy nhất quan trọng là tổng dung lượng bộ nhớ được sử dụng để lưu trữ các ô chứ không phải số lượng các ô.
Justin

1
Đồng ý với Kragen và Joe. Đừng lo lắng về những gì nghe có vẻ nhiều - hãy làm toán và giải quyết nó. Nó không phải là một vấn đề.
Kylotan
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.