Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Manuelles Wechseln von Szenen

Manchmal ist es hilfreich, mehr Kontrolle darüber zu haben, wie man zwischen Szenen wechselt. Wie oben erwähnt, werden die Child-Nodes eines Viewport in dem Bild gerendert, das er erzeugt. Dies gilt auch für Nodes außerhalb der "aktuellen" Szene. Autoloads fallen in diese Kategorie, aber auch Szenen, die man zur Laufzeit instanziiert und dem Baum hinzufügt:

var simultaneous_scene = preload("res://levels/level2.tscn").instantiate()

func _add_a_scene_manually():
    # This is like autoloading the scene, only
    # it happens after already loading the main scene.
    get_tree().root.add_child(simultaneous_scene)

Um den Zyklus zu schließen und die neue Szene mit der alten auszutauschen, müssen die Entwickler eine Entscheidung treffen. Es gibt viele Strategien, um eine Szene aus der Ansicht des Viewport zu entfernen. Die Kompromisse beinhalten ein Gleichgewicht zwischen Laufzeitgeschwindigkeit und Speicherverbrauch sowie ein Gleichgewicht zwischen Datenzugriff und -integrität.

  1. Wir können die bestehende Szene löschen. SceneTree.change_scene_to_file() und SceneTree.change_scene_to_packed() werden die aktuelle Szene sofort löschen. Der Entwickler kann aber auch die Hauptszene löschen. Angenommen, der Name des Root-Nodes ist "Main", könnte man get_node("/root/Main").free() ausführen, um die gesamte Szene zu löschen.

    • Der Speicher wird endladen.

      • Vorteil: RAM wird nicht mehr für die unnötigen Sachen verschwendet.

      • Nachteil: Die Rückkehr zu dieser Szene ist jetzt teurer, da sie wieder in den Speicher geladen werden muss (benötigt Zeit UND Speicher). Kein Problem, wenn eine baldige Rückkehr nicht erforderlich ist.

      • Nachteil: Sie haben keinen Zugriff mehr auf die Daten dieser Szene. Kein Problem, wenn die baldige Verwendung dieser Daten nicht erforderlich ist.

      • Hinweis: Es kann nützlich sein, die Daten in einer bald zu löschenden Szene beizubehalten, indem Sie einen oder mehrere seiner Nodes erneut an eine andere Szene anhängen oder sogar direkt an SceneTree.

    • Die Prozessierung stoppt.

      • Vorteil: Keine Nodes bedeutet keine Prozessierung, keine Physik-Prozessierung oder keine Eingabebehandlung. Die CPU steht zur Verfügung, um den Inhalt der neuen Szene zu bearbeiten.

      • Nachteil: Die Prozessierung und Eingabeverarbeitung dieser Nodes funktioniert nicht mehr. Kein Problem, wenn die Verwendung der aktualisierten Daten nicht erforderlich ist.

  2. Wir können die vorhandene Szene ausblenden. Durch Ändern der Sichtbarkeit oder Kollisionserkennung der Nodes können wir den gesamten Node-Unterbaum aus der Sicht des Spielers ausblenden.

    • Der Speicher ist noch vorhanden.

      • Vorteil: Man kann bei Bedarf immer noch auf die Daten zugreifen.

      • Vorteil: Es ist nicht erforderlich, weitere Nodes zu verschieben, um Daten zu speichern.

      • Nachteil: Es werden mehr Daten im Speicher gehalten, was auf speichersensitiven Plattformen wie Web oder Mobile zu einem Problem wird.

    • Die Prozessierung geht weiter.

      • Vorteil: Daten erhalten weiterhin Verarbeitungsaktualisierungen, sodass die Szene alle darin enthaltenen Daten aktualisiert, die auf Delta-Zeit oder Framedaten beruhen.

      • Vorteil: Nodes sind immer noch Bestandteil von Gruppen (da Gruppen zum Szenenbaum gehören).

      • Nachteil: Die Aufmerksamkeit der CPU wird jetzt auf beide Szenen aufgeteilt. Zu viel Last kann zu niedrigen Frameraten führen. Man sollte unbedingt die Performance testen, um sicherzustellen, dass die Target-Plattform der Belastung standhalten kann.

  3. Wir können die vorhandene Szene aus dem Baum entfernen. Weisen Sie dem Root-Node der vorhandenen Szene eine Variable zu. Verwenden Sie dann Node.remove_child (Node) um die gesamte Szene vom Baum zu trennen.

    • Der Speicher ist noch vorhanden (ähnliche Vor- und Nachteile wie beim Ausblenden).

    • Die Verarbeitung wird gestoppt (ähnliche Vor- und Nachteile wie beim vollständigen Löschen).

    • Vorteil: Diese Variante des "Ausblendens" ist viel einfacher zu ein- und auszublenden. Anstatt möglicherweise mehrere Änderungen an der Szene zu verfolgen, muss nur das eine Methodenpaar add/remove_child aufgerufen werden. Es ähnelt dem Deaktivieren von Spielobjekten in anderen Engines.

    • Nachteil: Anders als beim Ausblenden mittels Sichtbarkeit werden die in der Szene enthaltenen Daten nicht aktualisiert, wenn sie auf Delta-Zeit, Eingaben, Gruppen oder anderen vom Szenenbaum abgeleiteten Daten beruhen.

Es gibt auch Fälle, in denen viele Szenen gleichzeitig vorhanden sein sollen. Möglicherweise fügt man zur Laufzeit einen eigenen Singleton hinzu oder behält die Daten einer Szene zwischen Szenenänderungen bei (Hinzufügen der Szene zum Root-Node).

get_tree().root.add_child(scene)

Vielleicht möchten sie stattdessen mehrere Szenen gleichzeitig mit SubViewportContainern anzeigen. Dies ist optimal in Fällen, in denen die Absicht besteht, verschiedene Inhalte in verschiedenen Teilen des Bildschirms darzustellen. Minimaps und Split-Screen-Multiplayer sind gute Beispiele.

Jede Option hat ihre eigenen optimalen Anwendungsfälle. Daher muss man die Auswirkungen jeder Option prüfen und entscheiden, welcher Weg am besten zu der jeweiligen Situation passt.