Jump to content
Unity Insider Forum

Speicherung / Simulierung Paralleler Level


Neoxit

Recommended Posts

Huhu meine lieben!

 

Da ich mich bisher nicht mit Dingen wie Speichern / Laden beschäftigt habe kommt mal eine Frage:

 

Hat Unity intern schon eine möglichkeit den gesamten Status, also wirklich so wie es ist (Das Level) komplett zu Speichern? Eine art "SaveWholeLevel()" Methode o.ä?

 

Ansonsten:

Wie würdet ihr es angehen, wenn ihr ein wirklich komplexes Level habt, wo ihr aber alles 1:1 Speichern und Laden wollt? Müsste wirklich jede einzelne variable, Liste, GameObject Vektoren etc. per hand in eine Datei gelesen werden?

 

 

Desweitern eine kleine weitere Frage:

 

Ist es möglich, Level Synchron laufen zu lassen? Hat das schonmal jemand versucht?

Meine alternative wäre natürlich sonst eine Routine laufen zu lassen die weiter "Simuliert" während man ausserhalb des levels ist, jedoch wäre das glaube ich ein extremes Unterfangen. Oder?

 

Wie macht ihr übrigens den Levelwechsel, wenn der Spieler bspw: Level 1 Startet, dort einen NPC hat der dir z.b. bis zum Level 2 folgt, dann tippert ihr n bisschen in Level 2 rum und geht zurück zu Level 1, aber so, das der NPC dort steht, wo er zuletzt standet, direkt als ihr das level verlassen habt.

 

Im Prinzip hängen diese 3 Fragen ziemlich zusammen, und es geht hier hauptsächlich um das selbe Prinzip des Save/Loads.

 

Euer Neoxit

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hiho,

 

zuerst: Nein, so eine SaveAll gibt es nicht. Du könntest halt durch alle Objekte iterieren und diese serialisieren, aber das ist glaube ich nicht besonders praktisch und deswegen lassen wir das mal weg.

 

Das Problem hatte ich auch mal. Du musst dir mal überlegen, welche Informationen für dich wirklich wichtig sind. Bei dem Charakter ist es klar:

  • Die Werte des Charakters (Stärke, HP, Zustände etc.)
    Zustände kannst du z.B. durch eine Bitmaske repräsentieren, also Vergiftet | Blind | Schwach ergibt dann 1 | 0 | 1 ...
  • Das Inventar musst du dann wohl einzeln speichern, indem du einfach von vornherein jedes Objekt eines Inventars ein Interface implementieren lässt mit den Methoden Load und Save. Dann speicherst du einfach den Typen des Objekts (z.B. HealthBig) und seinen Status (z.B. 75%). Das ist dann easy zu machen

Bei der Umwelt ist es so eine Sache. Du musst ja nicht die Map speichern, die hast du ja schon irgendwo gespeichert und erstellt. Das Einzige, was du hier speichern müsstes, wären die Änderungen des Levels. Aber hier musst du dich bereits fragen, ob es das wert ist. In Gothic 3 konnte man ja auch sein Inventar auf dem Boden ablegen und es blieb erhalten ... das hat mich manchmal tierisch genervt, weil es einfach hässlich war ... in anderen Spielen war es genau andersherum, dort wurde alles immer zerstört, wenn man es abgelegt hat. Einmal verklickt und *puff*.

 

Aber genau das wird ja auch dein Gameplay wiedergeben ... wenn du dir an dieser Stelle etwas überlegst, was einigermaßen gut ist, dann bist du gleich fein raus. Wie ist es eigentlich noch mal in Borderlands? Da bleiben die Sachen nicht levelübergreifend liegen, oder? Einmal raus aus dem Level und alles ist weg.

 

Du hast ja noch gefragt, ob man jede einzelne Variable speichern muss ... nein, muss man nicht. Nur die, die wichtig sind und nicht rekonstruiert werden können. In Datenbanken gibt es die sogenannten schwachen Attribute. Das sind Attribute, die aus anderen Attributen hergeleitet werden. Beispiel: Das Geburtsdatum deines Charakters ist der 13.07.2012. Macht es Sinn hier noch extra das Alter abzuspeichern? Nein ... du kennst das Geburtsdatum und das heutige Datum, also kannst du es errechnen ... etc. etc. ... so kannst du all Attribute betrachten und sagen, welche wichtig sind und welche nicht. Wenn du von Beginn sauber arbeitest, wirst du keine schwachen Attribute haben und dann bleiben nur noch die wichtigen übrig und die musst du alle speichern.

 

Aber auch hier kann man mehrere Variablen in einander verschachteln, um Platz zu speichern. Beispiel: Du hast drei Attribute mit einem Max-Wert von 64 ... das bedeutet, dass du 6Bit zum abspeichern brauchst ... also kannst du eine Integer nehmen mit 64 Bit und packst da 10 Variablen rein, indem du shiftest etc..

 

Level synchron laufen lassen ... hm ... ich habe noch nicht weiter darüber nachgedacht, aber bei meinem Projekt, sollte das auch möglich sein. Ich wechsel zwischen Stadtteilen und die Brände sollen trotzdem weitergehen. Da muss man sich überlegen, was wichtig ist und wie wichtig es wirklich ist. In meinem Fall habe ich ja die gesamte Karte als eine Matrix und die Brände sind ebenfalls eine Matrix. Ich habe eine Funktion, die mir die Ausbreitung und Stärke der Flammen berechnet ... diese kann ich also im Hintergrund immer laufen lassen und somit die eigentliche Matrix manipulieren. Wenn der Charakter nun wieder in den brennenden Stadtteil geht, dann werden alle Flammen aktualisiert dargestellt. Der Aufwand ist minimal, da ich nur mit 2 Matrizen arbeite und eine simple Funktion ablaufen lasse.

 

Du musst dir halt überlegen, ob es eine Funktion für das gibt, was du simulieren willst. Genau darauf baut ja alles auf: eine Funktion. So ist es ja auch in SimCity (nicht 5).

 

Deine letzte Frage bzgl. der Startpositionen der Charaktere ... ne, da würde ich mir keinen Ast abbrechen. Mach es wie in Baldur's Gate oder Fallout. Dort hast du halt einen Bereich, wo du die Map verlässt und wirst auf der neuen Map ungefähr auf der gleichen Höhe positioniert. Den Unterschied erkennt man sowieso nicht. Das sind Details, die keinen interessieren. Mir ist in F.E.A.R. (dem Scheißspiel ... jetzt kommen die Flamebots :D ) aufgefallen, dass alle Wandtexturen gleich sind ... die wiederholen sich mit jedem Tile ... aber stört nicht. Merkt man auch nur, wenn man die Wand anstarrt, so wie ich.

 

Muss jetzt schnell los.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Zu 1:

Der Mark hat so etwas gemacht. Nennt sich glaube ich SaveIt und gibt es als Light und Kaufversion im UnityStore.

 

Zu 2:

Ja, alles was veränderbar ist müsstest du abspeichern. Also welches Objekt, wo ist es , wie es ausgerichtet ist, welche Eigenschaften es hat, in welche Richtung es sich gerade bewegt oder welches Ziel es gerade ansteuert, ob Forces auf es wirken und wenn ja, dann welche, etc...

 

Zu 3:

Synchron kann es nur dann laufen, wenn es nicht wirklich in einer anderen Szene ist. Wenn es an einem anderen Teil der Szene Passiert, den du nicht siehst.

 

Zum Levelwechsel und dem NPC:

Beim Levelwechsel musst du die NPC Daten speichern. Dass muss nicht zwingend auf Festplatte sein, es reichen Arrays oder Listen, die vom NPC beschrieben wurden und die beim Zurückkehren wieder ausgelesen werden, damit der NPC sich dort wirder instanzieren kann.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wie würdet ihr es angehen, wenn ihr ein wirklich komplexes Level habt, wo ihr aber alles 1:1 Speichern und Laden wollt? Müsste wirklich jede einzelne variable, Liste, GameObject Vektoren etc. per hand in eine Datei gelesen werden?

 

Tritt dieser Fall in der Praxis häufig auf? In dem Moment, wo du baking verwendest (was man in vielen Fällen braucht, um akzeptable Ergebnisse zu bekommen - sei es für die Vorberechnung von Licht, Occlusion Culling oder Pathfinding), gibt es einige statische Objekte in der Szene, deren Zustand sich nie ändert (zumindest nicht die Position ;-) ).

 

Die willst du schonmal nicht speichern, weil die ja eh statisch sind. Dann gibt es Objekte, die zwar dynamisch sind, die du aber ebenfalls nicht speichern willst, weil sie beispielsweise nur den GUI-Zustand abbilden.

 

Und dann gibt es - normalerweise einen eher kleinen Teil - von Objekten, die tatsächlich Zustand haben, den du beim Speichern sichern möchtest, und beim Laden wieder herstellen. Und auf die würde ich mich konzentrieren. Dazu hat Mr. Clown ja Einiges geschrieben ;-)

 

Ist es möglich, Level Synchron laufen zu lassen? Hat das schonmal jemand versucht?

Meine alternative wäre natürlich sonst eine Routine laufen zu lassen die weiter "Simuliert" während man ausserhalb des levels ist, jedoch wäre das glaube ich ein extremes Unterfangen. Oder?

 

Kommt darauf an, wie du das meinst ;-) ... lokal, bei Einzelplayer-Spielen schaltest du normalerweise alles ab, was der Spieler gerade nicht sieht. Dort gehst du also einen Schritt in die genau entgegengesetzte Richtung: Selbst im aktuellen Level schaltest du die Simulation von allem, was du nicht unbedingt brauchst, einfach ab. Bei den meisten Game-Designs merkt der Spieler das nicht, also wäre es vergeudete CPU Zeit.

 

Bei einem Game-Design, bei dem das auffällt, würde ich mir zuerst die Frage stellen: Brauche ich das wirklich? Wenn die auf Teufel komm raus mit "Ja" beantwortet wird, würde ich tatsächlich zu Tricks raten, die möglichst effizient laufen. Vielleicht kannst du das, was da "simuliert" werden soll ja irgendwie mit weniger Overhead berechnen? Vielleicht so, dass du es erst "on demand" berechnen musst, also kurz bevor der Spieler es zu sehen bekommt (und dann auch nur das, was der Spieler tatsächlich gleich zu sehen bekommen wird ;-) ).

 

Eine ganz andere Sache: Bei Multiplayer-Spielen möchtest du vielleicht auf einem Server parallel mehrere "Sessions" laufen lassen. Das ist, was man teilweise als "Instanzen" kennt, geht darüber aber auch hinaus: Bei Traces of Illumination beispielsweise habe ich 12 Level, und die sollen auf einem Server alle aktiv sein. So können zwei Gruppen gleichzeitig in einem Level spielen, ohne sich zu sehen oder sonstwie zu beeinflussen. Ebenso können aber auch drei Gruppen in verschiedenen Levels spielen.

 

Der eine Teil, wie ich das gelöst habe: Die Level haben unterschiedliche Koordinaten. So kann ich auf dem Server alle Level gleichzeitig laden und aktiv halten. Der Part ist relativ einfach. Schwieriger war, dass verschiedene Gruppen gleichzeitig im gleichen "Raum" (also im gleichen Level, mit den gleichen Koordinaten) spielen können. Das hat aber auch funktioniert. Der Trick war hier, die Physik und einige andere Sachen so einzurichten, dass beispielsweise Kollisionen zwischen Objekten verschiedener "Gruppen" von Unity gar nicht erst erkannt werden (inzwischen würde ich das mit Layer-based Collision versuchen, was allerdings auch trickreich ist - und damals gab's das noch gar nicht).

Link zu diesem Kommentar
Auf anderen Seiten teilen

Danke für die super Antworten Mr.Clown und Malzbie, und Jashan!

 

Das Problem wovor ich halt stehe betrifft mein CrystalSUN Projekt. Dabei geht es nämlich um die Simulierung von z.b. Transportrouten.

Derzeitig sind meine Level so organisiert, das ich z.b. für jeden Landebaren Planeten, für jede Station und für jeden Sektor eine eigene Szene besitze. Darunter z.b. auch die Schiffsmodifikationsszene. Nun beunruhigt mich das alles ein wenig, und habe ehrlich gesagt Angst, das Projekt erneut komplett umschreiben zu müssen / zum dritten mal neu aufziehen muss.

 

Das Parallele Simulieren liegt darin, wenn ich z.b. einen Transporter befehlige (dies soll u.a. auch möglich sein) und sage er soll Ware X in Sektor 1 Einkaufen, und Ware X in Sektor 2 Verkaufen, und dort Ware Y zu mir zurück bringen. Der Spieler sollte dabei aber nicht behindert werden selber weiter zu agieren wie er es möchte. Ich sage mal, Transporter die nicht zum Spieler gehören, seien mal dahin gestellt. Die müssen nicht ausserhalb des aktuellen Sektors weiter Simuliert werden.

 

Jetzt wisst ihr genau worum es sich dreht. #Panic

 

Gruß Neoxit

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du machst also eine Art X? Ja, ganz nett. Du hast doch deine Schiffe mit ihren Routen, ihren Geschwindigkeiten und dem Ziel. Damit kannst du ja super simulieren. Du bist in deiner Station und deine Transporter werden in eine Datei (nur als Beispiel) zwischengespeichert und in der Szene "Station" geladen und simuliert. Dabei werden dort aber wirklich nur die wichtigen Daten gehalten (also kein Prefab mit Texturen etc. ... sondern nur Zahlen wie ID, Speed, TargetID, Distance, InventarID ... und in jeder Sekunde auf der Station wird diese Liste an Transportern einfach simuliert. Also ... die Entfernung wird per Speed und Target einfach immer wieder neu berechnet und wenn die Entfernung zum Ziel = 0 ist, dann kannst du ein Prefab von dem Transporter in deiner Station andocken lassen und fertig.

 

Bei Weltraumsimulationen müsste es eigentlich ganz gut gehen, da hier kein unnützes Zeug mit berücksichtigt werden muss (Bäume etc.) ... bei der Simulation kannst du auch gleich ObstacleAvoidance berücksichtigen, weil sonst deine simulierten Reisen immer kürzer sein werden als die echten Reisen (da immer nur die direkte Verbindung zwischen Transporter und Ziel simuliert wird, ohne Kollisionen). ^_^

 

Hoffe die Antwort taugt was. Bei meinem Projekt exestieren nur Theorien ... und einige Algorithmen für die Ausbreitung und Lebensdauer von Feuer, Wasser, Eis und so ... wie gut es in der Realität sein wird ... weiß noch nicht so genau. Das Feuer ruckelt auf jeden Fall, sobald ein Waldbrand entsteht. Zu viele Partikel etc. ... da muss ich noch was machen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...