Saya sudah mencari jawaban tetapi saya tidak dapat menemukan pendekatan terbaik untuk menangani fungsi / perhitungan yang mahal.
Dalam permainan saya saat ini (bangunan kota berbasis ubin 2d) pengguna dapat menempatkan bangunan, membangun jalan, dll. Semua bangunan membutuhkan koneksi ke persimpangan yang harus ditempatkan pengguna di perbatasan peta. Jika bangunan tidak terhubung ke persimpangan ini, tanda "Tidak terhubung ke jalan" akan muncul di atas bangunan yang terkena dampak (jika tidak harus dihapus). Sebagian besar bangunan memiliki radius dan mungkin terkait satu sama lain juga (misalnya pemadam kebakaran dapat membantu semua rumah dalam radius 30 ubin). Itulah yang saya juga perlu perbarui / periksa ketika koneksi jalan berubah.
Kemarin saya mengalami masalah kinerja yang besar. Mari kita lihat skenario berikut ini: Seorang pengguna tentu saja dapat juga menghapus bangunan dan jalan. Jadi, jika seorang pengguna sekarang memutuskan koneksi setelah persimpangan saya perlu memperbarui banyak bangunan pada saat yang sama . Saya pikir salah satu saran pertama adalah untuk menghindari loop bersarang (yang jelas merupakan alasan besar dalam skenario ini) tetapi saya harus memeriksa ...
- jika bangunan masih terhubung ke persimpangan jika genteng jalan telah dihapus (saya melakukan itu hanya untuk bangunan yang terkena dampak oleh jalan itu). (Mungkin masalah yang lebih kecil dalam skenario ini)
daftar ubin radius dan dapatkan bangunan dalam radius (loop bersarang - masalah besar!) .
// Go through all buildings affected by erasing this road tile. foreach(var affectedBuilding in affectedBuildings) { // Get buildings within radius. foreach(var radiusTile in affectedBuilding.RadiusTiles) { // Get all buildings on Map within this radius (which is technially another foreach). var buildingsInRadius = TileMap.Buildings.Where(b => b.TileIndex == radiusTile.TileIndex); // Do stuff. } }
Ini semua memecah FPS saya dari 60 hingga hampir 10 selama satu detik.
Saya juga bisa melakukannya. Gagasan saya adalah:
- Tidak menggunakan utas utama (fungsi Perbarui) untuk yang satu ini tetapi utas lainnya. Saya mungkin mengalami masalah penguncian ketika saya mulai menggunakan multithreading.
- Menggunakan antrian untuk menangani banyak perhitungan (apa yang akan menjadi pendekatan terbaik dalam kasus ini?)
- Simpan lebih banyak informasi di objek saya (bangunan) untuk menghindari lebih banyak perhitungan (misalnya bangunan dalam radius).
Dengan menggunakan pendekatan terakhir saya bisa menghapus satu sarang dalam bentuk foreach ini sebagai gantinya:
// Go through all buildings affected by erasing this road tile.
foreach(var affectedBuilding in affectedBuildings) {
// Go through buildings within radius.
foreach(var buildingInRadius in affectedBuilding.BuildingsInRadius) {
// Do stuff.
}
}
Tapi saya tidak tahu apakah ini cukup. Gim seperti Kota Skylines harus menangani jauh lebih banyak bangunan jika pemain memiliki peta besar. Bagaimana mereka menangani hal-hal itu ?! Mungkin ada antrian pembaruan karena tidak semua bangunan melakukan pembaruan pada saat yang sama.
Saya menantikan ide dan komentar Anda!
Terima kasih banyak!