Dies kann für Spiele mit genau definiertem Umfang einfach sein, aber die Frage betrifft Sandbox-Spiele, bei denen der Spieler alles erstellen und bauen darf .
Mögliche Techniken:
- Verwenden Sie Speicherpools mit Obergrenze.
- Löschen Sie regelmäßig nicht mehr benötigte Objekte.
- Weisen Sie zu Beginn zusätzliche Speicherkapazität zu, damit diese später als Wiederherstellungsmechanismus freigegeben werden kann. Ich würde sagen, um 2-4 MB.
Dies ist bei Mobil- / Konsolenplattformen wahrscheinlicher, bei denen der Speicher im Gegensatz zu Ihrem 16-GB-PC normalerweise begrenzt ist. Ich gehe davon aus, dass Sie die vollständige Kontrolle über die Speicherzuweisung / Freigabe haben und keine Speicherbereinigung erforderlich ist. Das ist der Grund, warum ich dies als C ++ etikettiere.
Bitte beachten Sie, dass ich nicht über Effective C ++, Punkt 7 "Seien Sie auf Bedingungen mit unzureichendem Arbeitsspeicher vorbereitet" , spreche , obwohl dies relevant ist, würde ich gerne eine Antwort in Bezug auf die Spieleentwicklung sehen, bei der Sie normalerweise mehr Kontrolle darüber haben, was ist Ereignis.
Um die Frage zusammenzufassen: Wie bereiten Sie sich auf nicht genügend Arbeitsspeicher für Sandbox-Spiele vor, wenn Sie auf eine Plattform mit eingeschränkter Speicherkonsole / Handy abzielen?
quelle
Antworten:
Im Allgemeinen gehen Sie nicht mit zu wenig Arbeitsspeicher um. Die einzig vernünftige Option in Software, die so umfangreich und komplex wie ein Spiel ist, besteht darin, so schnell wie möglich in Ihrem Speicher-Allokator abzustürzen / zu bestätigen / zu beenden (insbesondere bei Debug-Builds). Zu wenig Arbeitsspeicher wird in einigen Fällen auf Kernsystem- oder Serversoftware getestet und verarbeitet, in der Regel jedoch nicht an anderer Stelle.
Wenn Sie eine höhere Speicherkapazität haben, stellen Sie stattdessen sicher, dass Sie nie mehr als diese Speicherkapazität benötigen. Sie können beispielsweise eine maximale Anzahl zulässiger NPCs gleichzeitig behalten und einfach aufhören, neue nicht-essentielle NPCs zu erzeugen, sobald diese Obergrenze erreicht ist. Für wichtige NPCs können Sie entweder festlegen, dass sie nicht wichtige ersetzen, oder Sie können einen separaten Pool / Cap für wichtige NPCs einrichten, um die sich Ihre Designer kümmern (z. B. wenn Sie nur 3 wichtige NPCs haben können, werden die Designer nicht mehr als 3 einsetzen Ein Bereich / Block - gute Werkzeuge helfen Designern dabei, dies richtig zu tun, und Tests sind natürlich unerlässlich.
Ein wirklich gutes Streaming-System ist auch wichtig, insbesondere für Sandbox-Spiele. Sie müssen nicht alle NPCs und Gegenstände im Speicher behalten. Während Sie sich durch Teile der Welt bewegen, werden neue Teile und alte Teile gestreamt. Dazu gehören im Allgemeinen NSCs und Gegenstände sowie Gelände. Design- und Konstruktionsbeschränkungen für Item-Limits müssen unter Berücksichtigung dieses Systems festgelegt werden. Dabei ist zu beachten, dass höchstens X alte Chunks beibehalten und proaktiv geladen werden. Y neue Chunks werden geladen, sodass das Spiel Platz für alle behalten muss Die Daten von X + Y + 1 Blöcken im Speicher.
Einige Spiele versuchen, Situationen mit unzureichendem Arbeitsspeicher mit einem Ansatz mit zwei Durchläufen zu behandeln. Denken Sie daran, dass die meisten Spiele viele technisch unnötige zwischengespeicherte Daten enthalten (z. B. die oben genannten alten Blöcke), und eine Speicherzuweisung kann etwa Folgendes bewirken:
Dies ist eine letzte Maßnahme, um mit unerwarteten Situationen in Releases umzugehen. Während des Debuggens und Testens sollten Sie jedoch wahrscheinlich sofort abstürzen. Sie möchten sich nicht auf solche Dinge verlassen müssen (insbesondere, weil das Löschen der Caches schwerwiegende Auswirkungen auf die Leistung haben kann).
Sie könnten auch in Betracht ziehen, hochauflösende Kopien einiger Daten zu sichern. Beispielsweise könnten Sie die höher aufgelösten Mipmap-Ebenen von Texturen sichern, wenn Ihnen der GPU-Speicher (oder ein Speicher in einer Architektur mit gemeinsamem Speicher) ausgeht. Dies erfordert jedoch in der Regel viel architektonische Arbeit, um es wert zu machen.
Beachten Sie, dass einige sehr unbegrenzte Sandbox-Spiele auch auf dem PC ziemlich einfach zum Absturz gebracht werden können (denken Sie daran, dass die gängigen 32-Bit-Apps nur einen Adressraum von 2 bis 3 GB haben, selbst wenn Sie einen PC mit 128 GB RAM haben; ein 64-Bit-Computer). Bit-Betriebssystem und Hardware ermöglichen die gleichzeitige Ausführung von mehr 32-Bit-Apps, können jedoch nichts tun, um eine 32-Bit-Binärdatei mit einem größeren Adressraum auszustatten. Am Ende haben Sie entweder eine sehr flexible Spielwelt, die in jedem Fall unbegrenzten Speicherplatz benötigt, oder Sie haben eine sehr begrenzte und kontrollierte Welt, die in begrenztem Speicher (oder irgendwo dazwischen) immer perfekt funktioniert.
quelle
Die Anwendung wird normalerweise auf der Zielplattform mit den Worst-Case-Szenarien getestet und Sie sind immer auf die Plattform vorbereitet, auf die Sie abzielen. Im Idealfall sollte die Anwendung niemals abstürzen, aber abgesehen von der Optimierung für bestimmte Geräte stehen Ihnen nur wenige Optionen zur Verfügung, wenn eine Warnung zu wenig Arbeitsspeicher angezeigt wird.
Die beste Vorgehensweise besteht darin, Pools vorab zuzuweisen, und das Spiel verwendet von Anfang an den gesamten benötigten Speicher. Wenn Ihr Spiel maximal 100 Einheiten hat, haben Sie einen Pool für 100 Einheiten und das wars. Wenn 100 Einheiten die Speicheranforderungen für ein Zielgerät überschreiten, können Sie die Einheit optimieren, um weniger Speicher zu verwenden, oder das Design auf maximal 90 Einheiten ändern. Es sollte keinen Fall geben, in dem Sie unbegrenzte Dinge bauen können, es sollte immer eine Grenze geben. Es wäre sehr schlecht, wenn ein Sandbox-Spiel
new
für jede Instanz verwendet würde, da Sie die Mem-Nutzung niemals vorhersagen können und ein Absturz viel schlimmer ist als eine Einschränkung.Außerdem sollte das Spieldesign immer die Geräte mit den niedrigsten Zielen berücksichtigen, denn wenn Sie Ihr Design mit "unbegrenzten" Dingen ausstatten, wird es viel schwieriger, die Speicherprobleme zu lösen oder das Design später zu ändern.
quelle
Nun, Sie können ungefähr 16 MiB (nur um 100% sicher zu sein) beim Start oder sogar
.bss
beim Kompilieren zuweisen und einen "sicheren Allokator" mit einer Signatur wieinline __attribute__((force_inline)) void* alloc(size_t size)
(__attribute__((force_inline))
ist ein GCC /mingw-w64
Attribut, das das Inlinen kritischer Codeabschnitte erzwingt) verwenden Auch wenn Optimierungen deaktiviert sind (auch wenn sie für Spiele aktiviert sein sollten)malloc
, versuchenvoid* result = malloc(size)
Sie stattdessen , und falls dies fehlschlägt, löschen Sie die Caches, geben Sie den freien Speicher frei (oder teilen Sie anderen Code mit, das.bss
Ding zu verwenden , aber das ist für diese Antwort nicht möglich) Leeren Sie nicht gespeicherte Daten (speichern Sie die Welt auf der Festplatte, wenn Sie ein Minecraft-ähnliches Konzept von Chunks verwenden, rufen Sie so etwas wie aufsaveAllModifiedChunks()
). Wenn dasmalloc(16777216)
(erneutes Zuweisen dieser 16 MiB) fehlschlägt (erneut durch analog für ersetzen.bss
), beenden Sie das Spiel und zeigen SieMessageBox(NULL, "*game name* couldn't continue because of lack of free memory, but your world was safely saved. Try closing background applications and restarting the game", "*Game name*: out of memory", MB_ICONERROR)
oder eine plattformspezifische Alternative. Alles zusammenfassen:Sie können eine ähnliche Lösung mit verwenden ,
std::set_new_handler(myHandler)
womyHandler
wirdvoid myHandler(void)
das genannt , wennnew
fehlschlägt:quelle