Bagaimana saya bisa menyimpan semua data level saya dalam satu file alih-alih tersebar di banyak file?

8

Saat ini saya menghasilkan data level saya, dan menyimpan ke disk untuk memastikan bahwa setiap modifikasi yang dilakukan pada level disimpan.

Saya menyimpan "potongan" 2048x2048 piksel ke dalam file. Setiap kali pemain bergerak ke bagian yang tidak memiliki file yang terkait dengan posisi, file baru dibuat.

Ini berfungsi dengan baik, dan sangat cepat. Masalah saya, adalah saat Anda memainkan jumlah file semakin besar.

Saya bertanya-tanya apa saja teknik yang dapat digunakan untuk mengurangi jumlah file, tanpa membuat kinerja menjadi hit. Saya tertarik pada bagaimana Anda akan menyimpan / mencari / memperbarui data ini dalam satu file, bukan beberapa file secara efisien.

jallan
sumber
5
Anda pada dasarnya harus menulis sistem file miniatur untuk dapat menyimpan semuanya dalam satu file. Ini akan menambah kompleksitas dan mungkin tidak sepadan.
thedaian
1
Saya tidak benar-benar memiliki banyak pengalaman dengan yang berikut ini, tetapi mungkin nosql db berbasis file ( stackoverflow.com/questions/2403174/… ) bisa menjadi pilihan.
Chris
Berapa banyak file yang kita bicarakan di sini? Apakah pemain menghasilkan puluhan ribu file, atau hanya ratusan? Apa yang diubah pemain di chunk? Apakah chunk menghasilkan langkah yang mahal (yaitu, apakah Anda perlu men-cache seluruh chunk vs hanya berbeda?)
Leniency
Minecraft juga melalui konversi ini di beberapa titik. Saya percaya itu dimulai sebagai mod kemudian dimasukkan ke build utama. Layak untuk dilihat. minecraftwiki.net/wiki/Region_file_format
MichaelHouse
1
@thedaian sedikit lebih rumit tetapi Anda dapat melakukan beberapa hal keren dan benar-benar mengurangi waktu mencari jika Anda mau bekerja ekstra dalam memori sehingga sistem file tidak harus melakukannya pada disk.
ClassicThunder

Jawaban:

7

Cara tercepat untuk melakukan ini adalah menyimpan segala sesuatu dalam satu file dan lompat kursor ke potongan yang ingin Anda baca. Setelah Anda menekan disk membaca urutan dari titik itu cukup cepat.

Beberapa hit ke INode yang berbeda untuk menemukan lokasi file pada volume fisik yang mengambil sebagian besar waktu dan juga apa skala yang buruk.

Selain itu, karena ini dinamis, Anda juga akan memerlukan peta yang menyimpan offset dalam file untuk setiap chunk.

Pada Disk

[Chunk 1][Chunk 2][Chunk 3][Chunk 4][Chunk 5][Chunk 6][Chunk 7][Chunk 8][Chunk 9]

Terlihat

[7][8][9]
[6][1][2]
[5][4][3]

Maka Anda hanya perlu membuka aliran yang membaca dari file tetapi tidak mengunci aliran / proses lain dari mengaksesnya. Maka Anda perlu membaca dari offset yang benar untuk jarak yang benar. Saya percaya C # di bawah ini.

var chunk = new byte[4194304];
using (var file = new FileStream (openFileDialog1.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    using (var reader = new StreamReader (file, Encoding.Unicode)) {
        reader.Read(chunk, offset * 4194304, 4194304);
    }
}

Sekarang karena fakta bahwa Anda membuka aliran dalam mode readonly dan memungkinkan orang lain untuk Baca / Tulis, Anda dapat terus menambahkan potongan baru sampai akhir. Catat nomor offset mereka dan jangan mencoba membacanya sebelum mereka ada di sana.

PS Anda tidak akan ingin menggunakan blok menggunakan karena Anda akan ingin hanya 1 aliran membaca sepanjang umur tingkat apa pun yang Anda gunakan. Anda juga mungkin harus menyimpan pemetaan chunk ke file lain saat keluar tetapi itu hanya satu beban ketika Anda memuat level Anda.

Klasik
sumber
Ini memberi saya beberapa ide bagus. Apakah metode ini mengharuskan Anda untuk menulis setiap byte jumlah byte yang persis sama? Saya akan membayangkan, karena pencarian offset akan membutuhkannya.
jgallant
Selama Anda memiliki byte pertama dan berapa lama setiap potongannya tidak harus berukuran sama. Anda hanya perlu memiliki sesuatu di memori melacak dua bagian data ini.
ClassicThunder
1
Tentu saja, jika Anda tidak memilikinya dengan ukuran byte yang sama, Anda harus melakukan banyak perubahan jika ukurannya bertambah.
MichaelHouse
1

Bergantung pada waktu yang dibutuhkan untuk membuat chunk, Anda bisa menyimpan diff atau keadaan saat ini (lokasi musuh, dll). Saat pemain bergerak kembali ke chunk, ia menghasilkan lagi menggunakan seed yang disimpan, kemudian memuat perubahan apa pun yang dibuat dari file.

Jika pemain diizinkan untuk membuat perubahan signifikan, ini mungkin lambat dan file diff masih akan cukup besar, tetapi hanya untuk perubahan kecil, harus menjadi operasi yang murah. Beberapa chunk diffs dapat dikonsolidasikan ke dalam satu file juga - sesuatu yang berukuran cukup yang dapat dimuat ke dalam memori.

Anda mungkin tidak ingin memindahkan semua diff ke dalam satu file - yang membuka sejumlah masalah lain dengan memori, atau mengubah bagian tengah file.

Kelonggaran
sumber
1

Saya tahu ini adalah thread yang cukup lama - tetapi saya hanya ingin berpadu bahwa saya pikir arsip ZIP mungkin merupakan cara terbaik untuk pergi ke sini. Anda mendapatkan kompresi dengan data Anda (jika Anda menggunakan bitmap mentah, khususnya), keterbacaan dalam sistem operasi, dan Anda mendapatkan file tunggal seperti yang Anda inginkan.

Vaughan Hilts
sumber
0

Bagaimana dengan pemindaian dir untuk memeriksa cap waktu file di direktori level data vs file aktif saat ini dan memberikan rahmat dari file sebelumnya dan file maju setiap 10 detik atau lebih, dan apa pun yang tidak digunakan hapus saja.

Kecuali Anda mengharuskan pemain untuk kembali. Kemudian hanya membersihkan data level setelah penyelesaian level atau pos pemeriksaan? Bisa jadi besar pasti, tapi saya tidak berpikir ada banyak pilihan yang tersedia di sini

RedactedProfile
sumber
0

Bagaimana dengan beberapa potongan per file? Anda mengatakan potongan Anda adalah 2048 x 2048, bagaimana kalau menempatkan 16384 x 16384 dalam file. Tandai yang mana saja yang ada sehingga Anda tahu apakah Anda perlu membuatnya.

Loren Pechtel
sumber
0

Jika Anda dapat membuat potongan cukup cepat saat pemain menjelajahinya, maka Anda tidak perlu menyimpannya di disk sama sekali; yang perlu Anda lakukan adalah menyimpan seed untuk fungsi perlin noise yang Anda gunakan untuk menghasilkan konten prosedural Anda lagi sesuai permintaan.

Ini dapat disimpan dalam satu file, dan dapat ditulis secara berurutan dan diurutkan dalam RAM saat dimuat; tidak perlu untuk struktur yang rumit di dalam file itu sendiri pada disk. Anda dapat membaca dari itu hanya pada saat startup, dan menulis saat Anda menghasilkan 'halaman' baru (sebagaimana mereka disebut) di dunia game.

Akan
sumber