【问题标题】:Godot/Gdscript: Why is str2var not working on classes with _init method?Godot/Gdscript:为什么 str2var 不能使用 _init 方法处理类?
【发布时间】:2021-08-01 08:48:46
【问题描述】:

让我们定义 2 个类

A.gd

class_name A

var v = null

func _init(v_):
    v = v_

B.gd

class_name B

var v = null

现在,当我尝试使用 str2var/var2str 时,这就是我得到的结果

var a = A.new("aaa")
var b = B.new()
b.v = "bbb"

printt("var2str(a):", var2str(a))
printt("var2str(b):", var2str(b))

printt ("var2str(str2var(var2str(a))):", var2str(str2var(var2str(a))))
printt ("var2str(str2var(var2str(b))):", var2str(str2var(var2str(b))))

输出

var2str(a): Object(Reference,"script":Resource( "res://Scripts/AI/A.gd"),"v":"aaa")

var2str(b): Object(Reference,"script":Resource( "res://Scripts/AI/B.gd"),"v":"bbb")

var2str(str2var(var2str(a))):   Object(Reference,"script":null)

var2str(str2var(var2str(b))):   Object(Reference,"script":Resource( "res://Scripts/AI/B.gd"),"v":"bbb")

为什么 str2var(a) 不起作用?

我应该如何解决它?

【问题讨论】:

    标签: serialization godot gdscript


    【解决方案1】:

    解决方案

    通过使参数可选来修复它,例如:

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

    这样就没有错误了。我得到这个输出:

    var2str(a): Object(Reference,"script":Resource( "res://A.gd"),"v":"aaa")
    
    var2str(b): Object(Reference,"script":Resource( "res://B.gd"),"v":"bbb")
    
    var2str(str2var(var2str(a))):   Object(Reference,"script":Resource( "res://A.gd"),"v":"aaa")
    
    var2str(str2var(var2str(b))):   Object(Reference,"script":Resource( "res://B.gd"),"v":"bbb")
    

    问题

    对于抽象,str2var 不会将任何参数传递给_init反正它也不知道要传递什么。

    剩下的答案是确认str2var 将导致调用_init 而没有参数。


    当我尝试你的代码时,我得到了这个错误:

    E 0:00:00.630   _create_instance: Condition "r_error.error != Variant::CallError::CALL_OK" is true. Returned: __null
      <C++ Source>  modules/gdscript/gdscript.cpp:121 @ _create_instance()
      <Stack Trace> main.gd:12 @ _ready()
    

    通过查看source,我们可以在_create_instance 中找到引发错误的行。

    遗憾的是,这并没有给我太多信息。于是,我决定去研究一下str2var是如何实现的。

    我们在GDScriptFunctions::callhere 中找到它。哪个调用VariantParser::parse,哪个调用VariantParser::parse_value。我们对"Object" (here) 的情况感兴趣。这导致调用ClassDB::instance(type)。类型将是"Reference",然后它会继续设置所有属性。成为第一个"script":Resource("res://A.gd")

    当我们设置脚本 (here) 时,它会调用GDScript::instance_create。其中调用GDScript::_create_instance (here):

    return _create_instance(NULL, 0, p_this, Object::cast_to<Reference>(p_this) != NULL, unchecked_error)
    

    _init 没有参数(NULL 是参数数组,0 是参数数量)。这是GDScript::_create_instance的签名:

    GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error)
    

    当然,initializer-&gt;call(instance, p_args, p_argcount, r_error); 会失败,因为_init 需要一个参数。我们找到了将错误进一步向下抛出的行。 注意:initializer 是在解析脚本时创建的。

    【讨论】:

    • 令人印象深刻的答案,一如既往。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-08
    • 2019-08-09
    • 2012-09-08
    • 1970-01-01
    相关资源
    最近更新 更多