Ich habe für mein aktuelles Projekt an etwas sehr Ähnlichem gearbeitet. Dies ist ein kurzer Überblick darüber, wie ich es mache, mit einigen Randnotizen, wie man es sich ein bisschen einfacher machen kann.
Für mich bestand das erste Problem darin, die Welt in kleinere Teile zu zerlegen, die sich zum Laden und Entladen im Handumdrehen eignen. Da Sie eine kachelbasierte Karte verwenden, wird dieser Schritt erheblich einfacher. Anstatt die Positionen der einzelnen 3D-Objekte in der Ebene zu berücksichtigen, ist die Ebene bereits in Kacheln unterteilt. Auf diese Weise können Sie die Welt einfach in X-mal-Y-Kacheln aufteilen und diese laden.
Sie möchten dies automatisch und nicht von Hand tun. Da Sie XNA verwenden, haben Sie die Möglichkeit, die Inhaltspipeline mit einem benutzerdefinierten Exporter für Ihre Level-Inhalte zu verwenden. Sofern Sie keine Möglichkeit kennen, den Exportvorgang ohne Neukompilierung auszuführen, würde ich ehrlich davon abraten. Zwar ist das Kompilieren von C # nicht annähernd so langsam wie in C ++, dennoch müssen Sie Visual Studio nicht jedes Mal laden und Ihr Spiel neu kompilieren, wenn Sie eine geringfügige Änderung an der Map vornehmen.
Ein weiterer wichtiger Punkt ist, sicherzustellen, dass Sie eine gute Namenskonvention für die Dateien verwenden, die die Chunks Ihres Levels enthalten. Sie möchten wissen, dass Sie Block C laden oder entladen möchten, und dann den Dateinamen generieren, den Sie laden müssen, um dies zur Laufzeit zu tun. Denken Sie abschließend an Kleinigkeiten, die Ihnen später helfen könnten. Es ist wirklich schön, die Größe eines Blocks ändern zu können, erneut zu exportieren und dann die Auswirkungen auf die Leistung sofort zu sehen.
Zur Laufzeit ist es immer noch ziemlich einfach. Sie benötigen eine Möglichkeit, Blöcke asynchron zu laden und zu entladen. Dies hängt jedoch stark von der Funktionsweise Ihres Spiels oder Ihrer Engine ab. Ihr zweites Bild ist genau richtig - Sie müssen bestimmen, welche Chunks geladen oder entladen werden sollen, und die entsprechenden Anforderungen stellen, um dies zu tun, falls dies noch nicht geschehen ist. Je nachdem, wie viele Blöcke Sie gleichzeitig geladen haben, können Sie dies immer dann tun, wenn der Spieler eine Grenze von einem Block zum nächsten überschreitet. Schließlich möchten Sie so oder so sicherstellen, dass auch in der schlechtesten (angemessenen) Ladezeit der Block noch geladen ist, bevor der Player ihn sehen kann. Sie werden wahrscheinlich viel mit dieser Zahl spielen wollen, bis Sie ein ausgewogenes Verhältnis zwischen Leistung und Speicherverbrauch gefunden haben.
In Bezug auf die tatsächliche Architektur möchten Sie den Vorgang des tatsächlichen Ladens und Entladens der Daten aus dem Speicher von dem Vorgang des Bestimmens, was geladen / entladen werden soll, abstrahieren. Bei Ihrer ersten Iteration würde ich mir nicht einmal Gedanken über die Leistung beim Laden / Entladen machen und nur das Einfachste holen, das möglicherweise funktioniert, und sicherstellen, dass Sie die entsprechenden Anforderungen zu den entsprechenden Zeiten generieren. Anschließend können Sie das Laden optimieren, um den Müll zu minimieren.
Ich habe aufgrund der von mir verwendeten Engine eine Menge zusätzlicher Komplexität erlebt, aber das ist ziemlich implementierungsspezifisch. Wenn Sie Fragen zu meiner Arbeit haben, kommentieren Sie diese bitte und ich werde alles tun, um Ihnen zu helfen.