首页 > 解决方案 > Godot:未找到节点

问题描述

嗨,我目前正在制作一款包含 Godot 迷你游戏的游戏。在我完成第一个小游戏后,该小游戏只能在我玩那个特定场景时运行。

当我尝试运行我的整个项目(从主菜单屏幕开始)时,它会抛出一个错误(尝试在空实例上的基本“空实例”中调用函数“get_node”)说我的迷你游戏节点没有找到。所以我按下“本地”旁边的“远程”按钮,发现我的迷你游戏场景树不存在,这就是它无法检测到节点的原因。

我尝试将小游戏场景添加为自动加载。这使它工作,我可以再次从主菜单运行它,但是我的小游戏里面的东西不会加载,所以当它到达小游戏场景时它变成了一个空白屏幕。

我该如何做才能让我的小游戏正确加载并且可以从主菜单场景启动项目?

标签: godot

解决方案



新答案

因此,您在 Autoload 中的代码试图访问 Autoload 中没有的内容。

正如我在旧答案中所说,不能保证自动加载尝试访问的内容在那里。您不能依赖它被加载并可供自动加载。

当然,如果您从一个场景运行游戏,您可以相信该特定场景已加载。但如果你从另一个场景开始,那就不是这样了。那么在这种情况下你会怎么做呢?

好吧,您需要通过任何方式加载所需的场景(有关加载场景的方法,请参见旧答案)。您需要将实例传递给 Autoload。

传递该实例的一种方法是在 Autoload 中的代码中有一个函数,该函数将节点作为参数。然后在加载场景后,您可以调用传递实例的函数。

重申一下,您的主场景将加载小游戏场景(通过任何方式),因此它有一个实例。然后它将获取 Autoload,并在其上调用一个传递实例的函数。


让我们再试一次,在您的主场景中,您将加载小游戏。这可以通过不同的方式来实现。例如,load使用资源路径调用会给你一个PackedScene. 然后你调用whichinstancePackedScene你一个实例。

add_child之后,您可以使用...将该实例添加到场景树中

您将把它传递给 Autoload 的同一个实例。Autoload 中的代码需要一个变量来存储它,您将设置它。

在您的主场景中,您可以使用它get_node来获取自动加载(是的,自动加载可以是一个场景)。请参阅单例(自动加载)。然后使用您加载的实例设置变量。


为了完整起见,我还会提到您可以使用change_scene. 执行此操作时,Autoload 中的代码将保留。这可以使改变场景变得更简单。但是,如果您以后需要将一个单独的场景作为更大场景的一部分,或者如果您决定需要背景加载,那么依赖change_scene将是一个障碍。另请参见SceneTree手动更改场景


旧答案

首先是一些组织。你在哪里使用get_node

如果您get_node在主场景中使用来访问小游戏。没关系,你只需要确保小游戏已经加载并且在你需要的节点路径中。


请记住,要使用get_node您需要一个节点开始。因此,您调用的代码要么get_node是 a in a Node,要么是其他一些代码给它一个Node(例如作为函数调用的参数)。此外,你想要得到的东西必须在那里。

这些是有问题的案例:

  • 小游戏中的代码正在尝试访问小游戏中的其他内容。为此,请使用相对路径,这样无论小游戏加载到何处,它们都可以工作。同样,如果主场景正在访问主场景中的其他内容,那也没关系。
  • 小游戏中的代码试图访问另一个场景中的某些内容(例如主菜单)。避免这样做。改为使用信号进行这种 cummincation。在小游戏中访问自动加载是可以的。
  • Autoload 中的代码是一个场景(是的,您可以在 Autoload 中放置一个场景)试图访问不在 Autoload 中的内容。避免这样做。无法保证 Autoload 尝试访问的内容是否存在。
  • 自动加载中的代码在get_node节点上使用了一些其他代码给它。您可能可以让其他代码直接提供自动加载所需的节点。

请参阅节点通信了解节点路径


其次,您可能会认为代码中的其他一些事情是正确的,一旦将其加载到其他地方可能就不是这样了。如:

  • 当前的相机是什么相机。您可能需要在加载场景时更换相机,或者在代码中考虑当前相机的位置。
  • 场景根的位置在全局原点。您可能需要区分全局和局部位置,或者在加载场景时设置场景的位置。

第三,对于初学者来说,加载场景有很多方法:

  • 当然,您可以简单地将场景添加到场景树中。这是最简单的方法(我提醒您,您可以设置可见性)。这会增加场景的加载时间。总是从这个选项开始,只有当它给你带来问题时才转移到其他东西。
  • 你也可以把它放在自动加载上。自动加载适用于无论何时何地都应该可以访问的东西。我怀疑这是迷你游戏的情况。这会增加游戏的加载时间。

这些方法有一个重要的缺点:小游戏是抢先加载的。这可能会使游戏加载速度变慢。如果加载时间是个问题,您可能更愿意按需加载。为此,我们有更多选择:

  • 您可以PackedScene使用load(将资源路径作为参数传递)然后instance, 和add_child.
  • preload(将资源路径作为参数传递)来获取PackedScene. 然后当你需要它时,你可以instanceadd_child.
  • 您可以改为使用class_name(请参阅将脚本注册为类),它可以让您使用new. 如果它是一个节点,您可以在之后将其添加到场景树中add_child。它可能不是一个节点,这有时也很有用。顺便说一句,你可以给它静态函数,你可以在不实例化它的情况下调用它(没有静态变量,如果你想要静态变量使用 Autoload 代替)。
  • 您可以将场景放在场景树上,作为占位符。在场景面板(默认在编辑器左侧)上,打开场景节点上的上下文菜单(右键单击),然后选择“加载为占位符”。这会产生一个InstancePlaceholder节点。您可以replace_by_instance在需要时调用它。

退税?按需加载时,游戏将在加载时停止。如果您按需加载的单个内容足够小,那没问题。但是对于一个大场景,它可能是。这导致我们最终选择:

退税?与其他方法相比,它的代码要多得多。理想情况下,您会重复使用它。事实上,您可以将此逻辑放在 Autoload 上,这样它就可以在您需要加载某些内容的任何地方使用。

事实上,您可以使用后台加载来加载主菜单。然后主菜单可以加载它需要工作的所有内容,只需将它放在场景树中即可。这也意味着主菜单不是起始场景。相反,起始场景使用后台加载来加载主菜单。从视觉上看,它可能有一个标志和一个进度条,或者类似的东西。但是,此建议并非适用于所有游戏,仅适用于需要大量时间加载的游戏。


万一混淆:节点路径在场景树中,请参见get_nodeNodePath。并且资源路径在项目内部文件系统中(以 开头的res://),请参阅数据路径


推荐阅读