如何在重新启动Godot 4游戏时加载游戏数据?

huangapple go评论77阅读模式
英文:

How to load game data when restarting a godot4 game?

问题

在游戏中,它保存你的数据(进度)。如何在Godot 4引擎中实现这一点?我知道的唯一存储数据的方法是使用变量,但在重新启动游戏时会被重置。

有谁知道可以提供帮助的相关信息吗?

英文:

you know how in games, it saves your data(progress). How do you do that in the godot4 engine? The only way I know how to store data is using variables, but it gets reset when you re-launch the game.

Does anyone know anything about this that can help?

答案1

得分: 3

首先,您想要将要保存/加载的所有内容放在同一个地方。

如果数据分散在多个节点上,会更加困难。

因此,我们将拥有一个对象,它将暴露数据,以便需要它的代码可以读取它和写入它,并且还负责保存和加载它。


那么我们在哪里做这个?我们在一个autoload(单例)中进行,因为Godot可以在场景树的任何地方使用它们。

因此,创建一个autoload(单例)并为其命名。在那里,您将拥有要保存或加载的所有变量。您还可以拥有信号。

然后,您需要一些代码来加载和保存它们。类似这样的代码可以作为一个起点:

const save_file := "user://saved.dat"

func reload() -> void:
	var file := ConfigFile.new()
	var err := file.load(save_file)
	if err != OK:
		push_error("error loading score " + str(err))
		return

	score = int(file.get_value("Player", "score"))

func save() -> void:
	var file := ConfigFile.new()
	file.set_value("Player", "score", score)
	var err := file.save(save_file)
	if err != OK:
		push_error("error saving score " + str(err))

此示例基于我在回答问题当玩家触碰硬币的Area2D时增加得分时编写的示例。

该代码使用ConfigFile,它将创建一个可读的文件(基本上是INI文件)。它支持编码所有基本的Godot类型。

然后,就是在这些方法中包含您需要的变量。

当然,您可以从_ready中调用reload


您甚至可以尝试一些反射。例如:

extends Node

const save_file := "user://saved.dat"

func reload() -> void:
	var file := ConfigFile.new()
	var err := file.load(save_file)
	if err != OK:
		push_error("Error loading: " + str(err))
		return

	for property in get_property_list():
		if property.type == TYPE_NIL:
			continue

		set(property.name, file.get_value("Progress", property.name))

func save() -> void:
	var file := ConfigFile.new()
	for property in get_property_list():
		if property.type == TYPE_NIL:
			continue

		file.set_value("Progress", property.name, get(property.name))

	var err := file.save(save_file)
	if err != OK:
		push_error("Error saving: " + str(err))

在这里,我使用get_property_list来获取此对象公开的属性列表,然后从文件中保存或加载它们。这样,您不必在这些方法中硬编码变量。只需添加var并使用它们。


这并不是唯一的方法。然而,我提出的方法应该足够简单且灵活,适用于大多数情况。

有些人更喜欢使用JSON,而其他人更喜欢使用二进制格式。

我不建议使用Resource,除非您知道自己在做什么,因为Godot将加载资源文件而不进行验证,这可能允许将代码注入游戏。当然,这种预防措施更多是为了保护玩家免受某些不怀好意的人分享的存档文件的影响。

英文:

First and foremost, you want to keep everything you want to save/load in the same place.

If you have the data scattered across multiple nodes, you will have a harder time.

So we will have an object that will expose the data so that the code that needs it can read it and write it and you can put signals there too, and is also responsible for saving and loading it.


So where do we do that? We do it in an autoload (singleton), as Godot makes them available from anywhere in the scene tree.

So create an autoload (singleton) and give it a name. There you will have all the variables you want to save or load. And you can have signals too.

Then you need some code to load and save them. Something like this would be an start:

const save_file := "user://saved.dat"

func reload() -> void:
	var file := ConfigFile.new()
	var err := file.load(save_file)
	if err != OK:
		push_error("error loading score " + str(err))
		return

	score = int(file.get_value("Player", "score"))

func save() -> void:
	var file := ConfigFile.new()
	file.set_value("Player", "score", score)
	var err := file.save(save_file)
	if err != OK:
		push_error("error saving score " + str(err))

This example is based on the one I wrote as part of the answer to the question Increment score when player touches a coin's Area2D.

The code uses ConfigFile which will make a human readable file (basically an INI file). And it supports encoding all basic Godot types.

Then it is a matter of including the variables you need in these methods.

You can, of course, call reload from _ready.


You might even try a bit of reflection. For example:

extends Node

const save_file := "user://saved.dat"

func reload() -> void:
	var file := ConfigFile.new()
	var err := file.load(save_file)
	if err != OK:
		push_error("Error loading: " + str(err))
		return

	for property in get_property_list():
		if property.type == TYPE_NIL:
			continue

		set(property.name, file.get_value("Progress", property.name))

func save() -> void:
	var file := ConfigFile.new()
	for property in get_property_list():
		if property.type == TYPE_NIL:
			continue

		file.set_value("Progress", property.name, get(property.name))

	var err := file.save(save_file)
	if err != OK:
		push_error("Error saving: " + str(err))

Here I'm using get_property_list to get the list of properties exposed by this object, and either save them or load them from the file. This way you don't have to hard code the variables in these methods. Just add the vars and use them.


This is not the only way to go about this. Yet, the approach I present should be both easy and flexible enough for most cases.

Some people prefer JSON for example. Other prefer to use a binary format.

I'm not advising to use Resource unless you know what you are doing, because Godot will load resource files without validation, and this might allow to inject code into the game. Granted, that this precaution is more on protecting the player from some shady person who shared a save file with them.

huangapple
  • 本文由 发表于 2023年5月18日 08:03:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76276917.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定