如何让场景中的组节点完成的功能在改变场景后不改变?

发布于 2025-01-13 11:52:49 字数 130 浏览 1 评论 0 原文

我已将节点放入一个组中。我在场景脚本上添加了一个 func 来对组中的节点进行更改。在那个函数中,我使节点可以自由排队以及类似的东西。但是当我改变场景并返回到前一个场景时,排队的空闲又回来了,它不再是排队的空闲了。如何让它即使改变场景也不会改变?

I have put nodes in a group. And I have put a func on the scene script to make changes to the nodes in group. In that func,I made the nodes to queue free and stuffs like that. But when I change scene and come back to the previous scene,the queued free is back again,it is not queued free anymore. How do I make it not change even after changing scene?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

山人契 2025-01-20 11:52:49

为什么信息丢失

当您使用 change_scenechange_scene_to 当前场景被卸载,新场景被加载并实例化。

也许有助于概念化场景实例与存储中的场景不同。所以所发生的情况就像在编辑器中打开文件,修改但不保存它。


好吧,如果您确实想走这条路,这是一个解决方案:您可以保存场景。

首先创建一个PackedScene,例如:

var packed_scene := PackedScene.new()

然后告诉它打包场景的根节点,例如:

packed_scene.pack(self)

注意:任何节点没有其owner 属性设置为您在此处传递的 Node 将被忽略。不,add_child< /code> 不设置 owner 属性。

如果您一直在注意,您知道您可以给一个 PackedScene change_scene_to...但是当场景发生变化时如何保持它呢?

有几种方法。事实是:如果我们可以保留信息,我们可能不需要保存场景。


在自动加载中保留内容

即使您更改场景,您在项目设置中添加到自动加载(单个)的脚本和场景也会保留在那里(除非您明确删除它们)。

因此,保存信息的一个非常简单的方法是使用一个包含一些变量的脚本,您可以从项目中的任何位置写入和读取这些变量。您可以通过自动加载来做到这一点。


将事物保留在资源中

Godot 缓存资源。当您在多个位置加载相同的资源时,您实际上获得的是相同的对象。

好吧,您知道您可以创建自定义 资源< /a> 类。为此,请在“文件系统”面板的上下文菜单中选择“新建脚本”,然后在脚本中创建一个 扩展资源,并给它一个 class_name

然后,您可以通过选择“新资源”并在询问时选择您的Resource 类,从FielSystem 面板的上下文菜单中创建该Resource 的资源。

无论你在哪里加载其中一个,你都会得到相同的对象。是的,即使是在另一个场景。因此,您可以将变量添加到您的 Resource 类中,在一个场景中写入它们并在另一个场景中读取它们。

我在其他地方解释了一个更具体的示例。


将东西保存在存储中< /strong>

您可以写入文件并从文件中读取。例如,您可以这样做:

# save
var file = File.new()
file.open("user://a.sav", File.WRITE)
file.store_pascal_string(var2str(data))
file.close()

# load
file.open("user://a.sav", File.READ)
data = str2var(file.get_pascal_string())
file.close()

或者,如果您要存储的是 Resource(无论是 PackedScene,还是其他一些 Resource 类)包括自定义的),您可以使用 ResourceSaver< /a>和ResourceLoader

# save
ResourceSaver.save("user://a.tres", resource)

# load
resource = ResourceSaver.load("user://a.tres")

的当然,您也可以使用 加载,或预加载。您可能还对后台加载感兴趣。


顺便说一句,如果您要保存玩家进度,则将所有玩家进度数据放在单个对象中是有意义的。如果您要将所有数据保存在一个地方,那么将所有玩家进度数据保存在一个位置,那么将其放在始终可访问的地方并且即使在更改场景时也保留在某个地方是有意义的,因此:自动加载中的进度数据。奖励:您也可以将保存和加载到文件的功能放在那里。


不要改变场景

由于改变场景会带来问题 - 考虑另一种解决方案:不要。

您可以加载一个场景:

var packed_scene := load("res://scene.tscn") as PackedScene

然后创建它的一个实例:

var scene := packed_scene.instance()

然后将其添加到当前的场景树中:

add_child(scene)

是的,它是一个Node!这也意味着您可以...

scene.queue_free()

或者您可以简单地使用 remove_child 不会释放它,因此您可以稍后将其添加回来。

因此您可以控制加载或卸载的内容以及何时。这对于保留一些东西很有用(例如 UI、玩家角色等......)。 按照我在这里描述的方式进行操作的一个缺点是 get_tree().current_scene 对您不再有用。另请参阅手动更改场景

Why information is lost

When you change the current scene with change_scene or change_scene_to the current scene is unloaded, and the new one is loaded and instanced.

Perhaps it helps to conceptualize that the instance of the scene is not the same as the scene in storage. So what happens is like opening a file in an editor, modifying and not saving it.


Alright, that is one solution if you really want to go that route: you can save a scene.

First create a PackedScene, for example:

var packed_scene := PackedScene.new()

Then tell it to pack the root node of the scene, for example:

packed_scene.pack(self)

Note: any Nodes that don't have their owner property set to the Node you passed here will be ignored. And no, add_child does not set the owner property.

If you have been paying attention, you know you can give a PackedScene to change_scene_to... But how do you keep it around when the scene changes?

There are a few ways. And the thing is: if we can keep information around, we might not need to save the scene.


Keep things around in autoloads

The scripts and scene you add to your autoloads (singleton) in project settings stay there (unless you explicitly remove them) even when you change scene.

Thus, a very simple way to keep information around is to have a script with some variables that you can write and read from anywhere in your project. And you can do that with an autoload.


Keep things around in resources

Godot caches resources. When you load the same resource in multiple places, you actually get the same object.

Well, you know you can create a custom Resource class. To do that, on the context menu of the FileSystem panel select "New Script", and in the script make a class that extends Resource, and give it a class_name.

Then you can create resources of that Resource from the context menu of the FielSystem panel by selecting "New Resource" and picking your Resource class when asked.

Everywhere you load one of those, you are going to get the same object. Yes, even if it is in another scene. So you can add variables to your Resource class, write them in one scene and read them in another.

I explain a more concrete example elsewhere.


Keep things around in storage

You can write to a file and read from a file. For example you can do this:

# save
var file = File.new()
file.open("user://a.sav", File.WRITE)
file.store_pascal_string(var2str(data))
file.close()

# load
file.open("user://a.sav", File.READ)
data = str2var(file.get_pascal_string())
file.close()

Or, if what you want to store is a Resource (be it a PackedScene, or some other Resource class including a custom one), you can use ResourceSaver and ResourceLoader:

# save
ResourceSaver.save("user://a.tres", resource)

# load
resource = ResourceSaver.load("user://a.tres")

Of course, you can also load resources with load, or preload. You may also be interested in Background Loading.


By the way, if you are going to save player progress, having all the player progress data in a single object makes sense. And if you are going to have all the data you are keeping all the player progress data in a single place, it makes sense it would be somewhere it is accesible all the time and stays around even when you change scenes, thus: put the player progress data in an autoload. Bonus: you can put the functions to save and load to a file there too.


Don't change scenes

Since changing scenes brings problems - consider another solution: don't.

You can load an scene:

var packed_scene := load("res://scene.tscn") as PackedScene

Then make an instance of it:

var scene := packed_scene.instance()

Then add it to your current scene tree:

add_child(scene)

Yes, it is a Node! It also means you can…

scene.queue_free()

Or you can simply remove it with remove_child which does not free it, so you can add it back later.

So you would be in control of what gets loaded or unloaded and when. Which is useful to keep stuff around (e.g. the UI, the player character, etc...). A drawback of doing it the way I describe here is get_tree().current_scene would not be useful to you anymore. See also Change scenes manually.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文