Я уже искал ответы, но мне не удалось найти лучший подход для обработки дорогих функций / вычислений.
В моей текущей игре (двумерное городское здание на основе плиток) пользователь может размещать здания, строить дороги и т. Д. Все здания нуждаются в соединении с перекрестком, который пользователь должен разместить на границе карты. Если здание не подключено к этому перекрестку, над поврежденным зданием появится всплывающее сообщение «Не связано с дорогой» (в противном случае его необходимо удалить). Большинство зданий имеют радиус и могут быть связаны друг с другом (например, пожарная служба может помочь всем домам в радиусе 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.
}
}
Но я не знаю, достаточно ли этого. Такие игры, как Cities Skylines должны обрабатывать намного больше зданий, если у игрока есть большая карта. Как они справляются с этими вещами ?! Может быть очередь обновления, так как не все здания обновляются одновременно.
Я с нетерпением жду ваших идей и комментариев!
Большое спасибо!