Godot/Gdscript 实例序列化

Godot/Gdscript serialization of instances

如果我想在 Godot 中序列化一个数组,我可以这样做:

var a1 = [1 ,2 ,3]

# save
var file = File.new()
file.open("a.sav", File.WRITE)
file.store_var(a1, true)
file.close()

# load
file.open("a.sav", File.READ)
var a2 = file.get_var(true)
file.close()

print(a1)
print(a2)

输出(按预期工作):

[1, 2, 3]
[1, 2, 3]

但是如果我想序列化一个对象,像这样 class in A.gd:

class_name A
var v = 0

相同的测试,实例为 A:

# instance
var a1 = A.new()
a1.v = 10

# save
var file = File.new()
file.open("a.sav", File.WRITE)
file.store_var(a1, true)
file.close()

# load
file.open("a.sav", File.READ)
var a2 = file.get_var(true)
file.close()
print(a1.v)
print(a2.v)

输出:

10

错误(在线 print(a2.v)):

Invalid get index 'v' (on base: 'previously freed instance').

来自在线文档:

void store_var(value: Variant, full_objects: bool = false)

    Stores any Variant value in the file. If full_objects is true, encoding objects is allowed (and can potentially include code).

Variant get_var(allow_objects: bool = false) const

    Returns the next Variant value from the file. If allow_objects is true, decoding objects is allowed.

    Warning: Deserialized objects can contain code which gets executed. Do not use this option if the serialized object comes from untrusted sources to avoid potential security threats such as remote code execution.

它不是应该与 full_objects=true 一起使用吗?不然这个参数有什么用?

我的 classes 包含许多数组的数组和其他内容。我想 Godot 处理这种基本的序列化功能(当然,开发人员通常不得不在某一时刻保存复杂的数据),所以,也许我只是没有做我应该做的事情。

有什么想法吗?

要使 full_objects 正常工作,您的自定义类型必须从 Object 扩展(如果您没有指定 class 扩展的内容,它会扩展 Reference)。然后,序列化将基于导出的变量(或您在 _get_property_list 中所说的任何内容)。 顺便说一句,在您的情况下,这可以序列化您的自定义类型的整个脚本。您可以通过查看保存的文件来验证。

因此,full_objects 对于序列化扩展 Resource(不扩展 Object)的类型没有用。相反 Resource 序列化适用于 ResourceSaver, and ResourceLoader还有 loadpreload。是的,这就是您存储或加载场景和脚本(以及纹理、网格等……)的方式。


我相信更简单的代码解决方案是使用函数 str2varvar2str。这些会让你省去很多麻烦:

    # save
    var file = File.new()
    file.open("a.sav", File.WRITE)
    file.store_pascal_string(var2str(a1))
    file.close()

    # load
    file.open("a.sav", File.READ)
    var a2 = str2var(file.get_pascal_string())
    file.close()
    print(a1.v)
    print(a2.v)

无论您存储什么,该解决方案都有效。

也许这是一个解决方案(我没有测试过)

# load
file.open("a.sav", File.READ)
var a2 = A.new()
a2=file.get_var(true)
file.close()
print(a1.v)
print(a2.v)