Я вже шукав відповіді, але не зміг визначити найкращого підходу для обробки дорогих функцій / розрахунків.
У моїй теперішній грі (міська забудова на основі 2d) користувач може розміщувати будинки, будувати дороги тощо. Усі будівлі потребують підключення до вузла, який повинен розміщувати користувач на кордоні карти. Якщо будівля не підключена до цього перехрестя, над ураженою будівлею з’явиться знак «Не підключено до дороги» (інакше його потрібно буде зняти). Більшість будівель мають радіус і можуть бути пов’язані між собою (наприклад, пожежна частина може допомогти усім будинкам у радіусі 30 плиток). Це те, що мені також потрібно оновити / перевірити, коли змінюється дорожнє сполучення.
Вчора я зіткнувся з великою проблемою виступу. Давайте подивимось на такий сценарій: Користувач може, звичайно, також стерти будівлі та дороги. Отже, якщо користувач перерве з'єднання відразу після з'єднання, мені потрібно одночасно оновити багато будівель . Я думаю, що однією з перших порад буде уникати вкладених циклів (що, безумовно, є великою причиною в цьому сценарії), але я повинен перевірити ...
- якщо будівля все ще підключена до перехрестя у випадку, якщо дорожня плитка була видалена (я це роблю лише для постраждалих будівель цією дорогою). (У цьому сценарії може бути меншою проблемою)
список радіусних плиток і отримайте будівлі в радіусі (вкладені петлі - велика проблема!) .
// 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. } }
Це все розбиває FPS від 60 до майже 10 за одну секунду.
Так я міг би зробити. Мої ідеї:
- Не використовується головний потік (функція оновлення) для цього, але іншого потоку. Я можу зіткнутися з проблемами блокування, коли я починаю використовувати багатопотокові.
- Використання черги для обробки багатьох обчислень (що було б найкращим підходом у цьому випадку?)
- Зберігайте більше інформації в моїх об'єктах (будівлях), щоб уникнути більше обчислень (наприклад, будівлі в радіусі).
За допомогою останнього підходу я міг видалити одне гніздування у формі цього передбачення:
// 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.
}
}
Але я не знаю, чи цього достатньо. Такі ігри, як міста Skylines, повинні мати набагато більше будівель, якщо у гравця є велика карта. Як вони поводяться з цими речами ?! Може виникнути оновлення черги, оскільки не всі будівлі оновлюються одночасно.
Я з нетерпінням чекаю ваших ідей та коментарів!
Дуже дякую!