Ich habe bereits nach Antworten gesucht, konnte jedoch nicht den besten Ansatz für die Handhabung teurer Funktionen / Berechnungen finden.
In meinem aktuellen Spiel (ein auf 2 Kacheln basierendes Stadtgebäude) kann der Benutzer Gebäude platzieren, Straßen bauen usw. Alle Gebäude benötigen eine Verbindung zu einer Kreuzung, die der Benutzer am Rand der Karte platzieren muss. Wenn ein Gebäude nicht mit dieser Kreuzung verbunden ist, wird über dem betroffenen Gebäude ein Schild mit der Aufschrift "Nicht mit der Straße verbunden" angezeigt (andernfalls muss es entfernt werden). Die meisten Gebäude haben einen Radius und können auch miteinander verwandt sein (z. B. kann eine Feuerwehr allen Häusern in einem Radius von 30 Kacheln helfen). Das muss ich auch aktualisieren / überprüfen, wenn sich die Straßenverbindung ändert.
Gestern bin ich auf ein großes Leistungsproblem gestoßen. Schauen wir uns das folgende Szenario an: Ein Benutzer kann natürlich auch Gebäude und Straßen löschen. Wenn ein Benutzer jetzt direkt nach der Kreuzung die Verbindung unterbricht, muss ich viele Gebäude gleichzeitig aktualisieren . Ich denke, einer der ersten Ratschläge wäre, verschachtelte Schleifen zu vermeiden (was in diesem Szenario definitiv ein wichtiger Grund ist), aber ich muss überprüfen ...
- Wenn ein Gebäude noch mit der Kreuzung verbunden ist, falls eine Straßenkachel entfernt wurde (das mache ich nur für betroffene Gebäude auf dieser Straße). (Könnte in diesem Szenario ein kleineres Problem sein)
die Liste der Radiuskacheln und erhalten Gebäude innerhalb des Radius (verschachtelte Schleifen - großes Problem!) .
// 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. } }
Dies alles bricht meine FPS für eine Sekunde von 60 auf fast 10 herunter .
Könnte ich auch tun. Meine Ideen wären:
- Verwenden Sie nicht den Haupt-Thread (Update-Funktion) für diesen, sondern einen anderen Thread. Wenn ich Multithreading verwende, kann es zu Problemen beim Sperren kommen.
- Verwenden einer Warteschlange für viele Berechnungen (was wäre in diesem Fall der beste Ansatz?)
- Bewahren Sie mehr Informationen in meinen Objekten (Gebäuden) auf, um weitere Berechnungen zu vermeiden (z. B. Gebäude im Radius).
Mit dem letzten Ansatz könnte ich stattdessen eine Verschachtelung in dieser Form entfernen:
// 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.
}
}
Aber ich weiß nicht, ob das reicht. Spiele wie Cities Skylines müssen viel mehr Gebäude bewältigen, wenn der Spieler eine große Karte hat. Wie gehen sie mit diesen Dingen um?! Möglicherweise gibt es eine Aktualisierungswarteschlange, da nicht alle Gebäude gleichzeitig aktualisiert werden.
Ich freue mich auf Ihre Ideen und Kommentare!
Vielen Dank!