Já procurei respostas, mas não consegui descobrir a melhor abordagem para lidar com funções / cálculos caros.
No meu jogo atual (um edifício da cidade com base em blocos 2D), o usuário pode colocar edifícios, construir estradas etc. Todos os edifícios precisam de uma conexão com um cruzamento que o usuário deve colocar na borda do mapa. Se um edifício não estiver conectado a esta junção, um sinal de "Não conectado à estrada" aparecerá acima do edifício afetado (caso contrário, ele deverá ser removido). A maioria dos edifícios tem um raio e também pode estar relacionada (por exemplo, um corpo de bombeiros pode ajudar todas as casas em um raio de 30 peças). É isso que também preciso atualizar / verificar quando a conexão rodoviária muda.
Ontem, tive um grande problema de desempenho. Vamos dar uma olhada no seguinte cenário: É claro que um usuário também pode apagar prédios e estradas. Portanto, se um usuário agora interromper a conexão logo após o cruzamento , preciso atualizar muitos edifícios ao mesmo tempo . Acho que um dos primeiros conselhos seria evitar loops aninhados (o que definitivamente é um grande motivo nesse cenário), mas tenho que verificar ...
- se um prédio ainda estiver conectado à junção no caso de uma placa de estrada ter sido removida (eu faço isso apenas para edifícios afetados por essa estrada). (Pode ser um problema menor nesse cenário)
a lista de ladrilhos de raio e obtenha edifícios dentro do raio (loops aninhados - grande problema!) .
// 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. } }
Isso tudo divide meu FPS de 60 para quase 10 por um segundo.
Eu também poderia fazer. Minhas idéias seriam:
- Não usando o thread principal (função Atualizar) para este, mas outro thread. Eu posso ter problemas de bloqueio quando começar a usar o multithreading.
- Usando uma fila para lidar com muitos cálculos (qual seria a melhor abordagem nesse caso?)
- Mantenha mais informações em meus objetos (edifícios) para evitar mais cálculos (por exemplo, edifícios no raio).
Usando a última abordagem, eu poderia remover um aninhamento no formulário a seguir:
// 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.
}
}
Mas não sei se isso é suficiente. Jogos como Cities Skylines precisam lidar com muito mais construções se o jogador tiver um mapa grande. Como eles lidam com essas coisas ?! Pode haver uma fila de atualização, pois nem todos os edifícios são atualizados ao mesmo tempo.
Estou ansioso por suas idéias e comentários!
Muito obrigado!