Godot/GDScript:带_init方法的类调用str2var无效的原因及解决办法
问题根源
这个问题我之前也碰到过,核心原因是类A的构造函数_init需要传入参数,而Godot自带的str2var在反序列化自定义对象时,默认逻辑是先调用类的无参构造函数创建空实例,再从序列化字符串里读取属性值赋值给实例。
但类A没有提供无参的_init,str2var没法正确初始化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




