You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Godot/GDScript:带_init方法的类调用str2var无效的原因及解决办法

问题根源

这个问题我之前也碰到过,核心原因是类A的构造函数_init需要传入参数,而Godot自带的str2var在反序列化自定义对象时,默认逻辑是先调用类的无参构造函数创建空实例,再从序列化字符串里读取属性值赋值给实例。

但类A没有提供无参的_initstr2var没法正确初始化A的实例,只能生成一个没绑定脚本的空Reference对象——这就是为什么你看到反序列化后的A实例script变成了null,自然也恢复不了v属性。而类B用的是Godot默认的无参_init,所以整个反序列化流程能顺利走通,属性也能正常恢复。

解决办法

针对这个问题,有两种实用的解决思路:

1. 给类A加无参构造重载(最简单)

直接修改A类的_init方法,给参数设个默认值,让它支持无参调用:

# A.gd
class_name A
var v = null
func _init(v_ = null):
    v = v_

这样str2var就能正常调用无参的_init创建实例,再自动从序列化字符串里恢复v属性,你再测试的话,反序列化后的A实例就和原始的一模一样了。

2. 自定义序列化/反序列化逻辑(更灵活)

如果不想改构造函数的参数要求,可以让类A实现Godot的_serialize_deserialize方法,手动控制序列化和反序列化的过程:

# A.gd
class_name A
var v = null
func _init(v_):
    v = v_

# 自定义序列化:返回要存储的属性字符串
func _serialize():
    return var2str(v)

# 自定义反序列化:从字符串恢复属性
func _deserialize(data):
    v = str2var(data)

不过要注意,这种方式还是需要类能被str2var实例化,所以如果你的类必须保留带参构造,还可以用更手动的方式——用encode_json把对象的关键数据转成JSON,反序列化时手动加载脚本创建实例:

# 序列化A实例
var serialized_a = encode_json({
    "script_path": "res://Scripts/AI/A.gd",
    "v": a.v
})

# 反序列化A实例
var data = decode_json(serialized_a)
var restored_a = load(data["script_path"]).new(data["v"])

这种方式完全由你掌控对象的创建和属性恢复,适合有特殊需求的场景。

内容的提问来源于stack exchange,提问作者Cyrille

火山引擎 最新活动