Saat memuat peta ekstra besar, metode pemuatan membuang keluar dari memori di mana contoh baru ubin peta dibuat. Saya ingin seluruh peta diproses setidaknya pada aplikasi server (dan pada klien jika memungkinkan). Bagaimana saya mengatasi masalah ini?
UPD: pertanyaannya di sini adalah bagaimana membuat game berhenti mogok ketika masih ada memori bebas untuk digunakan. Adapun memecah peta dalam potongan, itu pendekatan yang baik, tetapi tidak apa yang saya inginkan dalam kasus saya.
UPD2: Pada awalnya saya pergi dan menetapkan tekstur untuk setiap instance baru dari kelas ubin dan itulah yang mengambil begitu banyak memori (juga memuat waktu). Sekarang dibutuhkan sekitar empat kali lebih sedikit ruang. Terima kasih untuk semua orang, sekarang saya dapat menjalankan peta besar tanpa berpikir untuk memecahnya menjadi potongan-potongan dulu.
UPD3: Setelah menulis ulang kode untuk melihat apakah array properti ubin bekerja lebih cepat atau mengkonsumsi lebih sedikit memori (dari properti yang disebutkan di ubin masing-masing sebagai properti objek), saya menemukan bahwa tidak hanya saya butuh banyak waktu untuk mencobanya, itu tidak membawa peningkatan kinerja, dan membuat permainan sangat sulit untuk di-debug.
sumber
Jawaban:
Ini sangat menyarankan bahwa Anda tidak mewakili ubin Anda dengan benar, karena ini berarti bahwa setiap ubin berukuran ~ 80 byte.
Yang perlu Anda pahami adalah bahwa perlu ada pemisahan antara konsep gameplay ubin, dan ubin visual yang dilihat pengguna. Dua konsep ini bukan hal yang sama .
Ambil Terraria sebagai contoh. Dunia Terraria terkecil membutuhkan 4200x1200 ubin, yaitu 5 juta ubin. Sekarang, berapa banyak ingatan yang diperlukan untuk mewakili dunia itu?
Nah, setiap ubin memiliki lapisan latar depan, lapisan latar belakang (dinding latar belakang), "lapisan kawat" di mana kabel pergi, dan "lapisan furnitur" di mana item furnitur pergi. Berapa banyak memori yang diambil setiap ubin? Sekali lagi, kita hanya berbicara secara konseptual, bukan secara visual.
Ubin latar depan dapat dengan mudah disimpan dalam waktu singkat yang tidak ditandatangani. Tidak ada lebih dari 65536 jenis ubin latar depan, jadi tidak ada gunanya menggunakan lebih banyak memori dari ini. Ubin latar belakang dapat dengan mudah berada dalam byte yang tidak ditandatangani, karena terdapat kurang dari 256 jenis ubin latar belakang yang berbeda. Lapisan kawat murni biner: salah satu ubin memiliki kawat di dalamnya atau tidak. Jadi itu satu bit per ubin. Dan lapisan furnitur lagi bisa menjadi byte yang tidak ditandatangani, tergantung pada berapa banyak kemungkinan potongan furnitur yang ada.
Total ukuran memori per ubin: 2 byte + 1 byte + 1 bit + 1 byte: 4 byte + 1 bit. Dengan demikian, ukuran total untuk peta Terraria kecil adalah 20790000 byte, atau ~ 20MB. (catatan: perhitungan ini didasarkan pada Terraria 1.1. Permainan telah berkembang banyak sejak saat itu, tetapi bahkan Terraria modern dapat masuk dalam 8 byte per lokasi ubin, atau ~ 40MB. Masih cukup dapat ditoleransi).
Anda seharusnya tidak pernah memiliki representasi ini disimpan sebagai array kelas C #. Mereka harus berupa array bilangan bulat atau yang serupa. AC # struct akan bekerja juga.
Sekarang, ketika tiba saatnya untuk menggambar bagian dari peta (perhatikan penekanannya), Terraria perlu mengubah ubin konseptual ini menjadi ubin yang sebenarnya . Setiap ubin harus benar-benar memilih gambar latar depan, gambar latar belakang, gambar furnitur opsional, dan memiliki gambar kawat. Di sinilah XNA hadir dengan berbagai sprite sheet dan semacamnya.
Yang perlu Anda lakukan adalah mengubah bagian yang terlihat dari peta konseptual Anda menjadi ubin sprite XNA yang sebenarnya. Anda seharusnya tidak mencoba mengubah semuanya sekaligus . Setiap ubin yang Anda simpan seharusnya hanya sebuah indeks yang mengatakan bahwa "Saya ubin tipe X," di mana X adalah bilangan bulat. Anda menggunakan indeks integer itu untuk mengambil sprite mana yang Anda gunakan untuk menampilkannya. Dan Anda menggunakan sprite sheet XNA untuk membuatnya lebih cepat dari sekadar menggambar paha depan individu.
Sekarang wilayah ubin yang terlihat perlu dipecah menjadi berbagai potongan, sehingga Anda tidak terus-menerus membuat lembaran sprite setiap kali kamera bergerak. Jadi Anda mungkin memiliki 64x64 bongkahan dunia sebagai sprite sheet. Potongan 64x64 mana pun di dunia terlihat dari posisi kamera pemain saat ini adalah bidak yang Anda gambar. Setiap potongan lain bahkan tidak memiliki sprite sheet; jika sepotong jatuh dari layar, Anda membuang lembar itu (catatan: Anda tidak benar-benar menghapusnya; Anda menyimpannya dan merespeknya untuk potongan baru yang mungkin akan terlihat kemudian).
Anda Server tidak perlu tahu atau peduli tentang representasi visual dari ubin. Yang perlu diperhatikan hanyalah representasi konseptual. Pengguna menambahkan ubin di sini, sehingga mengubah indeks ubin itu.
sumber
Membagi medan menjadi daerah atau bongkahan. Kemudian hanya memuat potongan yang terlihat oleh para pemain dan membongkar yang tidak. Anda bisa menganggapnya seperti ban berjalan, di mana Anda memuat bongkahan di satu ujung dan menurunkannya di ujung lainnya saat pemain bergerak. Selalu berada di depan pemain.
Anda juga dapat menggunakan trik-trik seperti memasang. Di mana jika semua ubin dari satu jenis hanya memiliki satu contoh di memori dan diambil beberapa kali di semua lokasi di mana itu dibutuhkan.
Anda dapat menemukan lebih banyak ide seperti ini di sini:
Bagaimana mereka melakukannya: Jutaan ubin di Terraria
'Zonasi' area di peta ubin besar, serta ruang bawah tanah
sumber
Jawaban Byte56 bagus, dan saya mulai menulis ini sebagai komentar untuk itu tetapi terlalu lama dan mengandung beberapa tips yang mungkin lebih membantu dalam sebuah jawaban.
Pendekatan ini sama baiknya untuk server dan juga untuk klien. Bahkan itu mungkin lebih tepat, mengingat bahwa server akan diminta untuk peduli tentang area yang jauh lebih banyak daripada klien. Server memiliki ide yang berbeda tentang apa yang perlu dimuat dari yang akan dilakukan klien (ia peduli dengan semua wilayah yang dipedulikan semua klien yang terhubung), tetapi server ini sama-sama mampu mengelola serangkaian wilayah kerja.
Bahkan jika Anda bisa memuat peta raksasa (dan kemungkinan besar tidak bisa) dalam memori, Anda tidak mau . Sama sekali tidak ada titik dalam memiliki data yang dimuat yang tidak langsung harus Anda gunakan, itu tidak efisien dan lambat. Bahkan jika Anda bisa memasukkannya ke dalam memori, kemungkinan besar Anda tidak akan dapat memproses semuanya dalam jangka waktu yang masuk akal.
Saya curiga keberatan Anda untuk memiliki wilayah tertentu diturunkan karena pembaruan dunia Anda beralih ke semua ubin dan memprosesnya? Itu memang valid, tetapi tidak menghalangi hanya memuat bagian-bagian tertentu. Alih-alih, saat suatu kawasan dimuat, terapkan pembaruan apa pun yang tidak terjawab, untuk memperbarui. Itu jauh lebih efisien dari segi pemrosesan juga (memusatkan upaya besar pada area memori yang kecil). Jika ada efek pemrosesan yang mungkin melintasi batas wilayah (misalnya aliran lava atau aliran air yang akan terbawa ke wilayah lain), maka ikat kedua wilayah tersebut bersama-sama sehingga ketika satu dimuat, begitu juga yang lainnya. Idealnya situasi itu akan diminimalkan, jika tidak Anda akan menemukan diri Anda kembali dengan cepat di kasus 'semua wilayah harus dimuat setiap saat'.
sumber
Cara efisien yang saya gunakan dalam game XNA adalah:
Anda juga bisa menggunakan peta besar tunggal dengan cara ini jika tidak terlalu besar dan menggunakan logika yang disajikan.
Tentu saja ukuran tekstur Anda harus seimbang dan resolusi membayar mahal untuk ini. Coba bekerja pada resolusi yang lebih rendah dan, jika perlu, buat paket res tinggi untuk memuat jika pengaturan konfigurasi diatur ke.
Anda harus mengulang hanya bagian yang relevan dari peta ini setiap kali dan hanya memberikan apa yang diperlukan. Dengan cara ini Anda akan banyak meningkatkan kinerja.
Sebuah server dapat memproses peta besar lebih cepat karena tidak harus membuat (salah satu operasi paling lambat) permainan, jadi logika untuk itu dapat berupa penggunaan potongan yang lebih besar atau bahkan seluruh peta, tetapi proses hanya logika sekitar pemain, seperti dalam 2 kali area tampilan pemain di sekitar pemain.
Saran di sini adalah saya sama sekali tidak ahli dalam dev permainan dan permainan saya dibuat untuk tugas akhir kelulusan saya (yang saya memiliki skor terbaik), jadi saya mungkin tidak begitu benar di setiap titik, tapi saya sudah meneliti web dan situs-situs seperti http://www.gamasutra.com dan situs pencipta XNA creators.xna.com (saat ini http://create.msdn.com ) untuk mengumpulkan pengetahuan dan keterampilan dan bekerja dengan baik untuk saya .
sumber
Antara
sumber
texture2d
? Apakah setiap ubin memiliki yang unik, atau apakah mereka berbagi tekstur? Juga, di mana Anda mengatakan ini? Anda tentu tidak memasukkannya ke dalam pertanyaan Anda, di mana informasi itu seharusnya berada. Tolong jelaskan keadaan spesifik Anda dengan lebih baik.Sebagai balasan untuk pembaruan Anda, Anda tidak dapat mengalokasikan array
Int32.MaxValue
dalam ukuran. Anda harus membaginya menjadi potongan-potongan. Anda bahkan bisa merangkumnya dalam kelas pembungkus yang memperlihatkan fasad seperti array:sumber