Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

手动更改场景

有时候, 有必要更好地控制如何交换场景. 如上所述, 一个 Viewport 的子节点将呈现给它生成的图像. 即使对于 "当前" 场景之外的节点, 这也适用. Autoloads属于这一类, 但是一个实例在运行时添加到树中的场景也是如此:

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)

要完成循环并将旧场景替换为旧场景, 开发人员可以选择制作. 从视图中删除场景有很多策略 Viewport. 权衡涉及平衡操作速度和内存消耗以及平衡数据访问和完整性.

  1. We can delete the existing scene. SceneTree.change_scene_to_file() and SceneTree.change_scene_to_packed() 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.

    • 卸载内存.

      • 好处: RAM不再拖累自重.

      • 坏处: 回到那个场景现在更加昂贵, 因为它必须再次加载回内存(需要时间和内存). 如果不久就回来是不必要的.

      • 坏处: 无法再访问该场景的数据. 如果不久就使用这些数据就不成问题了.

      • 注意: 通过将一个或多个节点重新附加到不同的场景, 甚至直接将其重新附加到 SceneTree, 可以将数据保存在即将删除的场景中.

    • 处理停止.

      • 好处: 没有节点意味着没有进程, 物理过程或输入处理. CPU可用于处理新场景的内容.

      • 坏处: 这些节点的处理和输入处理不再运行. 如果不需要使用更新的数据, 则不成问题.

  2. 我们可以隐藏现有场景. 通过更改节点的可见性或碰撞检测, 我们可以从游戏角色的角度隐藏整个节点子树.

    • 记忆仍然存在.

      • 好处: 如果需要, 仍然可以访问数据.

      • 好处: 无需再移动任何节点来保存数据.

      • 坏处: 更多数据被保存在内存中, 这将成为对内存敏感平台(如Web或移动设备)的问题.

    • 处理继续.

      • 好处: 数据继续接收处理更新, 因此场景将不断更新其中依赖于增量时间或帧数据的任何数据.

      • Pro: 节点仍然是组的成员(因为组属于 SceneTree).

      • 坏处: 现在CPU的注意力分散在两个场景之间. 负载过大可能导致帧速率降低. 应该确保测试性能, 以确保目标平台能够支持它们提供的负载.

  3. 我们可以从树上删除现有的场景. 给现有场景的根节点分配一个变量. 然后使用 Node.remove_child(Node) 来将整个场景从树上分离.

    • 记忆仍然存在(与从视图中隐藏它相似的优点/缺点).

    • 处理停止(类似于完全删除它的优点/缺点).

    • 好处:这种形式的“隐藏”更容易进行显示/隐藏。人们必须只调用一个方法 add / remove_child 方法,而不是潜在地跟踪场景的多个变化。它类似于在其他引擎中禁用游戏对象。

    • 坏处:与仅从视图中隐藏它不同,如果场景中包含的数据依赖于时间增量、输入、分组或其他通过访问 SceneTree 才能得到的数据,则它将变为陈旧。

在有些情况下, 人们可能希望有许多场景同时存在. 也许人们在运行时添加他们自己的单例, 或者在场景变化之间保留一个场景的数据(将场景添加到根节点).

get_tree().root.add_child(scene)

Perhaps instead they wish to display multiple scenes at the same time using SubViewportContainers. 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.

每个选项都有最合适的情况, 因此必须检查每个选项的效果并确定最适合其独特情况的路径.