Das hängt vom Umfang Ihres Spiels ab. Ein Vermögensverwalter ist für größere Titel unabdingbar, weniger für kleinere Spiele.
Bei größeren Titeln müssen Sie Probleme wie die folgenden bewältigen:
- Geteilte Assets - Wird diese Ziegelstruktur von mehreren Modellen verwendet?
- Lebensdauer des Assets - Wird dieses Asset, das Sie vor 15 Minuten geladen haben, nicht mehr benötigt? Zählen Sie Ihr Vermögen nach, um sicherzustellen, dass Sie wissen, wann etwas fertig ist usw
- Wenn in DirectX 9 bestimmte Asset-Typen geladen sind und Ihr Grafikgerät verloren geht (dies passiert unter anderem, wenn Sie Strg + Alt + Entf drücken), muss Ihr Spiel sie neu erstellen
- Laden Sie Assets, bevor Sie sie benötigen - ohne diese können Sie keine großen Open-World-Spiele erstellen
- Massenladen von Assets - Wir packen oft viele Assets in eine einzelne Datei, um die Ladezeiten zu verkürzen. Das Durchsuchen der Disc ist sehr zeitaufwändig
Bei kleineren Titeln sind diese Dinge weniger problematisch, Frameworks wie XNA haben Asset Manager in sich - es macht wenig Sinn, sie neu zu erfinden.
Wenn Sie feststellen, dass Sie einen Asset Manager benötigen, gibt es eigentlich keine einheitliche Lösung, aber ich habe festgestellt, dass eine Hash-Map mit dem Schlüssel als Hash * des Dateinamens (gesenkt und Trennzeichen alle "fest") funktioniert gut für die Projekte, an denen ich gearbeitet habe.
In der Regel ist es nicht ratsam, Dateinamen in Ihrer App fest zu codieren. In der Regel ist es besser, wenn ein anderes Datenformat (z. B. XML) Dateinamen in "IDs" darstellt.
- Als amüsante Randnotiz erhalten Sie normalerweise eine Hash-Kollision pro Projekt.
(Ich versuche, die "Don't use a Asset Manager" -Diskussion hier zu vermeiden, da ich sie für offtopisch halte.)
Eine Key / Value-Map ist ein sehr brauchbarer Ansatz.
Wir haben eine ResourceManager-Implementierung, in der Fabriken für verschiedene Ressourcentypen registriert werden können.
Die Methode "getResource" verwendet Vorlagen, um die richtige Factory für den gewünschten Ressourcentyp zu finden, und gibt ein bestimmtes ResourceHandle zurück (ebenfalls mithilfe der Vorlage, um ein bestimmtes ResourceHandle zurückzugeben).
Die Ressourcen werden vom ResourceManager (im ResourceHandle) neu gezählt und freigegeben, wenn sie nicht mehr benötigt werden.
Das erste Addon, das wir geschrieben haben, war die "reload (XYZ)" - Methode, mit der wir Ressourcen von außerhalb der laufenden Engine ändern können, ohne Code zu ändern oder das Spiel neu zu laden. (Dies ist wichtig, wenn Künstler an Konsolen arbeiten;))
Meistens haben wir nur eine Instanz des ResourceManagers, aber manchmal erstellen wir eine neue Instanz nur für eine Ebene oder eine Karte. Auf diese Weise können wir im levelResourceManager einfach "shutdown" aufrufen und sicherstellen, dass nichts ausläuft.
(kurzes) Beispiel
quelle
Engagierte Manager-Klassen sind so gut wie nie das richtige Engineering-Tool. Wenn Sie das Asset nur einmal benötigen (z. B. einen Hintergrund oder eine Karte), sollten Sie es nur einmal anfordern und es nach Abschluss des Vorgangs normal sterben lassen. Wenn Sie eine bestimmte Art von Objekt zwischenspeichern müssen, sollten Sie eine Factory verwenden, die zuerst einen Cache überprüft und andernfalls etwas lädt, es in den Cache stellt und es dann zurückgibt - und diese Factory kann einfach eine statische Funktion sein, die auf eine statische Variable zugreift , keine eigene Art.
Steve Yegge (unter vielen, vielen anderen) hat eine gute Geschichte darüber geschrieben, wie nutzlose Manager-Klassen aufgrund des Singleton-Musters am Ende sein können. http://sites.google.com/site/steveyegge2/singleton-considered-stupid
quelle
Ich habe immer gedacht, dass ein guter Vermögensverwalter mehrere Betriebsmodi haben sollte. Diese Modi wären höchstwahrscheinlich separate Quellmodule, die einer gemeinsamen Schnittstelle angehören. Die zwei grundlegenden Betriebsarten wären:
Sie benötigen ein Tool, mit dem Sie alle Assests aus der freigegebenen Datenbank abrufen und den Produktionsdatensatz erstellen können.
In meinen Jahren als Entwickler habe ich so etwas noch nie gesehen, obwohl ich nur für eine Handvoll Unternehmen gearbeitet habe, so dass meine Ansicht nicht wirklich repräsentativ ist.
Aktualisieren
OK, einige negative Stimmen. Ich werde diesen Entwurf erweitern.
Erstens brauchen Sie keine Factory-Klassen, denn wenn Sie haben:
Sie kennen den Typ, machen Sie also einfach:
Aber was ich oben versucht habe zu sagen, ist, dass Sie sowieso keine expliziten Dateinamen verwenden würden. Die zu ladende Textur wird durch das Modell bestimmt, auf dem die Textur verwendet wird. Es könnte sich um einen 32-Bit-Integer-Wert handeln, der für die CPU viel einfacher zu handhaben ist. Im Konstruktor für TextureHandle hätten Sie also:
AssetStream verwendet den Parameter resource_id, um den Speicherort der Daten zu ermitteln. Die Vorgehensweise hängt von der Umgebung ab, in der Sie ausgeführt werden:
In der Entwicklung: Der Stream sucht in einer Datenbank nach der ID (z. B. mit SQL), um einen Dateinamen zu erhalten, und öffnet die Datei. Die Datei kann lokal zwischengespeichert oder von einem Server abgerufen werden, wenn die lokale Datei nicht vorhanden ist oder vorhanden ist veraltet.
In Release: Der Stream sucht die ID in einer Schlüssel- / Wertetabelle, um einen Versatz / eine Größe in einer großen, gepackten Datei (wie der WAD-Datei von Doom) zu erhalten.
quelle
Was ich gerne für Assets mache, ist die Einrichtung eines Pauschalmanagers . Von der Doom-Engine inspiriert, sind Klumpen Datenelemente, die Assets enthalten und in einer Klumpendatei gespeichert sind , in der die Namen, Längen, der Typ (Bitmap, Sound, Shader usw.) und der Inhaltstyp (Datei, ein weiterer Klumpen usw.) angegeben sind die Klumpendatei selbst). Beim Start werden diese Klumpen in einen Binärbaum eingetragen, aber noch nicht geladen. Jede Karte (die auch ein Knoten ist) hat eine Liste von Abhängigkeiten, die einfach die Namen der Knoten sind, die die Karte benötigt, um zu funktionieren. Diese Klumpen werden, sofern sie nicht bereits geladen wurden, zum Zeitpunkt des Ladens der Karte geladen. Darüber hinaus werden die Klumpen der angrenzenden Karten geladen, und zwar nicht gleichzeitig, sondern wenn der Motor aus irgendeinem Grund im Leerlauf läuft. Dies kann die Karten nahtlos machen und es gibt keinen Ladebildschirm.
Meine Methode ist perfekt für Karten mit offener Welt, aber ein Level-basiertes Spiel wird nicht von der Nahtlosigkeit profitieren, die diese Methode für Sie mit sich bringt. Hoffe das hilft!
quelle