Szenen manuell ändern

Sometimes it helps to have more control over how one swaps scenes around. As mentioned above, a Viewport's child nodes will render to the image it generates. This holds true even for nodes outside of the "current" scene. Autoloads fall into this category, but so do scenes which one instances and adds to the tree at runtime:

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

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

public MyClass()
{
    simultaneousScene = (PackedScene)ResourceLoader.Load("res://levels/level2.tscn").instance();
}

public void _AddASceneManually()
{
    // This is like autoloading the scene, only
    // it happens after already loading the main scene.
    GetTree().GetRoot().AddChild(simultaneousScene);
}

To complete the cycle and swap out the new scene with the old one, developers have a choice to make. Many strategies exist for removing a scene from view of the Viewport. The tradeoffs involve balancing operation speed and memory consumption as well as balancing data access and integrity.

  1. We can delete the existing scene. SceneTree.change_scene() and SceneTree.change_scene_to() will delete the current scene immediately. Developers can also delete the main scene though. Assuming the root node's name is "Main", one could do get_node("/root/Main").free() to delete the whole scene.

    • Speicher freigeben.

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

      • Kontra: 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.

      • Kontra: 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.

    • Abarbeitung stoppt.

      • Pro: Kein Nodes bedeutet keinen Prozess, keinen physikalischen Prozess oder keine Eingabebehandlung. Die CPU steht zur Verfügung um den Inhalt der neuen Szene zu bearbeiten.

      • Kontra: Die Verarbeitung 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.

    • Speicher ist noch vorhanden.

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

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

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

    • Abarbeitung geht weiter.

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

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

      • Kontra: Die Aufmerksamkeit der CPU wird jetzt auf beide Szenen aufgeteilt. Zu viel Last kann zu niedrigen Bildraten führen. Man sollte sicher sein die Leistung zu testen, um sicherzustellen, dass die Zielplattform die gegebene Last unterstützt.

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

    • 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).

    • Pro: Diese Variante des "Versteckens" ist viel einfacher zu zeigen bzw. zu verstecken. 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.

    • Kontra: Anders als beim Ausblenden nur aus der Ansicht werden die in der Szene enthaltenen Daten veraltet, wenn sie auf Delta-Zeit, Eingaben, Gruppen oder anderen Daten beruhen, die abgeleitet sind vom Szenenbaum.

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 Wurzel-Node).

get_tree().get_root().add_child(scene)
GetTree().GetRoot().AddChild(scene);

Perhaps instead they wish to display multiple scenes at the same time using ViewportContainers. This is optimal in cases where the intent is to render different content in different parts of the screen. Minimaps and split-screen multiplayer are good examples.

Für jede Option gibt es Fälle für die sie am besten geeignet ist. Daher muss man die Auswirkungen der einzelnen Optionen untersuchen und bestimmen, welche davon am besten zu ihrer individuellen Situation passt.