Godot: 某些使用class_name的用法可能会意外产生循环错误

创建于 2018-08-26  ·  69评论  ·  资料来源: godotengine/godot

Windows 10 64位-Godot 3.1 alpha

编辑-改进了问题以关注周期性错误。

class_name某些用法在没有循环引用的情况下会产生循环错误,实际上有时没有给定单个引用之外的其他引用。

在使用is进行类比较时,我在工具脚本中最经常注意到这一点,但是在正常的脚本情况下有时似乎会发生这种情况。

在一个示例项目中重新创建它使我感到困惑。

godot master_2018-08-27_00-47-02

bug 3.2 confirmed high priority gdscript

最有用的评论

我正在进行的修复仍然是WIP并导致崩溃。 我不确定在Beta阶段合并如此大的更改,因此稍后可能会在3.2.x版本中完成。

所有69条评论

如果您给基本脚本一个class_name并在扩展行中使用它,它将起作用。
最初使用文件名时也会出现错误(https://github.com/godotengine/godot/blob/master/modules/gdscript/gdscript_parser.cpp#L4947),但它也消失了并且没有出现工作一次后返回(例如,在使用上述解决方法之后)

@ PetePete1984太好了

在进行双重检查和测试时,我正在查看get_class()方法,并且想知道它是否应该返回Node2D? is CustomClass部分返回_true_,但另一方面, is_class("CustomClass")是_false_。

CC @reduz @vnen @willnationsdev

我不会说这是预期的行为,尤其是不会出现错误消息,该消息暗示没有任何周期性包含。
get_class()is_class()通常令我感到困惑,无法对此发表评论。 消息人士从长远来看可能会解决这个谜,但是到目前为止, is对我来说已经足够了。

@vnen是否需要更清晰的错误消息?

@ PetePete1984是的, is在3.1中已经是一件了不起的事情。 虽然我确实遇到过这样的情况,我希望像match custom_thing.get_class()这样使用新的match match custom_thing.get_class()并与几个字符串进行比较。 但是没有什么关键的,只是可读性和较少键入的事情。

@avencherus您也许可以摆脱:

match custom_thing.get_script():
    <typename>: stuff # script classes
    <typename>: stuff
    _: match custom_thing.get_class():
        "Node": stuff # engine classes

我不确定为什么会出现此错误,我将不得不进行调查。

@willnationsdev不能完全确定get_script()部分中的检查内容,至少对我来说,它返回GDScript对象[GDScript:1057]

@vnen谢谢vnen。 X)当我回去尝试这些建议以查看是否可以为您提供更多信息时,似乎还有其他奇怪的事情发生。 我将稍作拉伸,重建和摆弄。 看看是否还有其他要添加的内容。 在此过程中,我可能还会遇到另一个问题。

@avencherus脚本类的“类名”是引用脚本的全局变量。 所以...

class_name CustomType
match get_script():
    CustomType:
        print("I am a CustomType!") # should print

@willnationsdev哦,很整洁,我明白了。 我不希望class_name这样工作,也不希望自定义类型可用于匹配模式。 感谢您分享此技巧。

@vnen是的,这个故事还有些皱纹。 让我看看我能说清楚什么。

首先,当给基类提供class_name时,Pete的解决方案有效。 我确实注意到的是,回到基类并取出我添加的class_name CustomBase ,它成功了一半。 添加节点时,它不再出现在节点列表中,但是is将起作用,并且没有奇怪的错误。

然后确认这一点,我重新创建了创建base2.gd-> custom2.gd扩展脚本的步骤。 然后在custom.gd内部使用class_name CustomClass2 ,但在基类中没有命名的类。

出现了另一个问题。 节点列表具有第一个节点,但是列出了带有“错误”的图标

godot master_2018-08-27_20-01-26

所以我修改了第一个基类,所以他们都使用class_name 。 但是又得到了奇怪的结果。

并非所有内容都显示在节点列表中,然后is关键字仅对其中一个返回true。 尽管在此屏幕截图中您可以看到节点列表可以识别CustomClass2,但是在其后面的代码中, is CustomClass2返回的是false。

godot master_2018-08-27_20-05-11

似乎很多事情都在切换或者在幕后徘徊。 我很难用有限的知识来预测它会做什么。

希望能有所帮助。 X)

编辑无视此评论。 我还没有意识到class_name在3.0.6中没有实现,这个问题还是指3,1构建。

class_name在3.0.6中似乎已损坏。 我将单独发出一个问题,但:

image

@bfishman脚本类不是

我只是尝试以下内容,并且每个版本都有效。 所有脚本类都显示在CreateDialog中,脚本可以很好地编译,场景可以成功运行,等等。

使用这样的场景层次结构:

  • 节点(base.gd)

    • 节点(derived.gd)

脚本:

# res://base.gd
extends Node
class_name BaseNode
func _ready():
    print("base")

# res://derived.gd
extends BaseNode
extends "base.gd" # I tried both of these 'extends' lines and they each worked
class_name DerivedNode # I tried with and without this line
func _ready():
    print("derived")

每次我运行测试时,都会打印

base
derived
base

...正如它应该。

我的建议是尝试清除编辑器的文件高速缓存(如果在编程/更新引擎的过程中文件高速缓存的存储方式发生了更改,可能会导致混乱,直到您将其清除为止)。

@willnationsdev感谢您的关注,我会尝试一下。 这是AppData / Roaming文件夹中的文件吗? 我现在将继续清除所有内容。 如果是这样,想知道是否还有我应该删除的更具体的内容吗?

@avencherus我不太确定。 我只是回想起@karroffel早些时候在脚本类图标中添加了一些修复程序时提到了一些相关信息。

https://github.com/godotengine/godot/commit/1093c0ff51b980634dffdd9618eaa53061da6419上进行了测试
我没有看到任何错误,但未在“创建新节点”对话框中显示该节点。

我也收到原始帖子中显示的错误(Windows x64 Godot 3.1 alpha):

image

但是,它发生在不同的上下文中。 我有3个脚本,每个脚本具有不同的class_name ,并且每个脚本都扩展了Node2D。 除非脚本之一使用is运算符引用该错误,否则不会发生该错误。 例如if some_var is Incomer 。 但是,很奇怪的是,如果同一脚本引用了另一个class_name,则没有问题。 而且,如果其他脚本引用了有问题的class_name,也没有问题。

因此,有一个ClassA,ClassB,ClassC。 如果ClassC使用is运算符引用ClassA,则在加载时出错。 如果ClassC引用ClassB,则没有错误。 如果ClassB引用ClassA,则没有错误。

没有一个脚本位于同一场景中,并且所有节点都是同级(没有祖先关系)。

@AlexHolly现在也和我一样。 该错误似乎消失了,但是是的,当没有使用class_name的基本脚本时,类也不会出现在添加节点窗口中。

这是在alpha 3.1 c320d93中

一个使用“ is”的小例子。 如果使用“ as”,可能会发生同样的事情。
@Oranjoose也提到了
cycle.zip

没有一个脚本位于同一场景中,并且所有节点都是同级(没有祖先关系)。

这与场景中的节点无关。 循环发生在脚本本身中。

现在,使用isas很容易获得周期,如果确实不是错误,那就是这样。 我会尝试改善这一点,但不适用于3.1。 原始报告是一个错误,因为代码中没有实际的周期。

我也无法在451e5fd中重现错误。 该节点未显示在创建窗口中。

我可以确认此问题在0dbe014(我提取的最新版本)中不存在。 我们可能可以解决此问题。

另外,我能够做到这一点,以便扩展脚本的脚本类仍显示在CreateDialog中,这仍然是一个错误。 PR在上方链接。

@willnationsdev谢谢威尔。 X)我一直在碰到class_name各种问题,但是还不能重新创建这个问题。 它们很难重新创建,但是从那以后我就停止使用它们了。

我注意到有时由于引用的脚本中的错误,脚本中可能出现模糊和不相关的错误。 当打开罪魁祸首脚本时,它们变得更有意义,并且在修复这些问题时也将它们清除。

不过,我将重新调整帖子的主题,因为这种周期性错误似乎确实仍然在特殊情况下发生,并且在尝试重新创建时难以捉摸。 因此,可能仍有一些问题,我将其开放给vnen。

@avencherus我明白了。 好吧,我希望您最终可以确定它在什么条件下发生。 没有上下文,我们将无法修复它。 XD

我注意到在godot-next工作中发生了一些周期性的引用错误,在那里我可以使用静态类型说我返回的类型与脚本的类名相同,但是如果我尝试实际引用类名脚本(以创建实例供以后返回该函数使用),将无法工作,因为脚本将引用自身,因此需要递归地无限加载。

我发现的解决方案是使用load(get_script().resource_path).new() 。 我知道这很麻烦,但是它允许解析器安全地构造数据并安全地通过编译过程,让类型名正式注册,然后仅在完全初始化后在RUNTIME引用该类型。

我会定期努力进行梳理。 希望我能得到更多帮助,但是我想象这些将不得不等到对实施有深刻了解的人在自己的项目上工作并首先解决这些问题。 我敢打赌,他们会在那种情况下将目光投向何方。

一些问题的简要摘要(我将在未来几周内将它们发布):

  1. 在执行obj is MyClass时,我会得到这些循环错误,并且两者之间没有其他连接或引用。 虽然我不知道它是否正在扫描场景树并将其子代计数为循环引用。
  2. 我也遇到了您所描述的不便之处。 我希望不是这样,因为它可以在相同类型的情况下与内置/本机类名称一起正常工作。 因此,您可以编写一堆代码,并以此为最终目的,以为一切都很好,直到您开始添加自定义类型,然后您不得不采用hack /替代方法/较旧的方法,然后它的值是否避免避免冗长的路径名?
  3. 我在编辑器中无错误地执行了这些操作,并在测试运行期间执行了清除操作,但是随后在导出的游戏中继续出现错误和失败。 下面的示例(尽管很可能与此问题无关)是class_name用法在构建中找不到其图标,但是在编辑器的运行和测试中没有问题。

gtc_2018-10-12_13-21-35

总体而言,我在class_name经历几乎是每天都会遇到的许多不可预测,难以解释且难以再现的错误。 很多时间被浪费在跳舞周围并试图解决它们上。

我真的很期待他们,他们绝对会使某些事情的编码更加紧凑和易读。 由于实际时间的原因,我不得不将它们放在一旁,并选择退出当前项目。

也许在4.0中。 X)

我将恢复到脚本路径的旧方法。 这样做是我自己的喜好,一直使用它们以避免任何随机的class_name意外,并保持代码更加一致。

如前所述,使用class_name创建循环非常容易,尤其是在使用isas 。 使用路径不太容易,但是您也可能遇到类似的问题。 问题是GDScript从未像这样进行工作,因此它在很大程度上取决于资源加载。 我有一些想法可以解决此问题(特别是仅忽略资源加载并直接对依赖项进行浅层解析),但这需要对解析器进行结构上的更改。

可能在下一版本中可能会正确解决,因为现在不是一个好时机。 class_name将是“较小功能”。 在某些情况下,您仍然可以使用它,但不能像您期望的那样广泛使用。

@vnen嘿。 欢迎回来。 X)

感谢您的答复和时间表。

是的,这就是为什么我现在必须将其搁置。 我有点迟钝地意识到这并不是一个如此平滑,合适或自然的整合。 (当我看到项目文件中的所有条目时,我对此有所暗示。)

我想这似乎是一个“较小”的功能,但是如果可以解决皱纹,它将具有一些非常重要的好处。 我真的很期待它,并且在已经使用它之后感觉到它的丢失。 对于GDScript,这绝对是一条不错的路。

我将缺少的一件事是当自定义类与新类型的提示结合使用时能够利用提示的功能。 var thing : NewThing

在几天之内(也许是几天后)第一次使用大型类时,我发现直到使用了几次之后,我才100%准确地记住了每个函数的名称。 因此,获得这些提示对我来说是一个意外而重大的生产力提升。 我能够在一个地区停留和工作更长的时间。

正如您所说,问题的核心当然是轻松的周期,但是我认为我最糟糕的经历是,当前某些错误没有指向正确的位置。 现在已经有几个星期了,但是我遇到过使用自定义类的情况,几天后一切都很好。 然后,我编写了更多代码来调用该自定义类,并且在开发过程中的某个时候,我开始遇到周期错误。 在某些情况下,这些错误对于解释错误发生的位置没有帮助。 为了找到它,我必须逐一查找并删除所有类名用法,直到错误停止。

仅仅发生了几起这样的事件就收回了很多收益。 我不敢想象会在30,000行中引发这样的问题。

一次让我震惊的事件是,循环错误仅出现在导出版本中,并引发了无关的脚本错误。 我认为有人说找不到图标纹理,但事实并非如此,当我放弃一些class_name用法时,它就被清除了。 我怀疑class_name失败,并且错误落在下一行。

我已经看到,有时会在原因之上或之下的线上发生错误。

我和我的零知识对于这些问题的很多根源真的很难。 许多内容对我来说只是一个幕后,我很感激您能够破译其中的一些内容。

在3.1中,出现了许多带有警告和错误的异常事件,因此我想知道问题是问题本身还是错误报告逻辑问题? 我还不知道从哪里开始,我只能希望其中的一些最终会有所帮助,而且随着时间的流逝,我也许可以将它们缩小到小型项目中。

编辑:没关系,我不知何故只是解决了循环包含问题...
反之,在启动编辑器时, project.godot的全局类将被覆盖。

@vnen@avencherus最好使用明确说明此错误的最终内容来更新OP,否则在理解好该错误之前需要进行冗长的讨论。

@ akien-mga我不太确定它的状态,或者具体写什么。

如果我还记得,至少有一部分。 预期的循环错误是GDScript当前形式的局限性,然后是意外出现的错误,这些错误在小型项目中很难隔离和再现(有时是由于错误消息不正确)。

由于这不是我当前正在使用的功能,因此我没有关注进度。 我认为自此以来,这里和那里的某些问题已经修复。

乍一看,这些其他问题似乎是关于GDScript中需要进行的更改的讨论。 针对3.2的修订。 如果那是计划,那么它将不再不在3.1里程碑之下。

除非vnen将其用于簿记,或者如果您更喜欢使用它来指代3.1.0稳定版本即将出现的重复问题,那么将其关闭可能很好。

该功能是我感兴趣的一项可用性优势,因此我很可能会在3.2版中进行重新访问,并发布所有发现。

好吧,这不应该被关闭,不,大量重复的报告肯定表明有需要解决的问题:)

我遇到以下错误消息,这对我将项目从3.0更新到3.1来说是有问题的。 以前,以下代码有效:

extends Node2D
export(String, FILE, "*.gd") var _class_name = "res://Test.gd"
onready var SomeClass = load(_class_name)

func foo():
    for c in get_children() :
        if c is SomeClass : 
            do_stuff()

当我将代码更改为:

extends Node2D
class_name SomeClass

func foo():
    for c in get_children() :
        if c is SomeClass : 
            pass

我收到以下错误:

解析错误:不允许在类文件中使用一个名称(创建循环引用)

这让我感到沮丧,因为我正在寻找的所有子节点都从该类继承,并且与其他没有的子节点混合在一起。 是否可以对脚本类的其他实例进行类型检查,而这种功能本打算无法以这种方式工作,而我应该采用另一种方式来做到这一点。

@Diaspater我认为您要做的就是将if c is SomeClass更改if c is get_script() 。 这两个选项都执行运行时检查,但是SomeClass版本要求您在编辑时再次加载脚本(导致循环引用),而get_script()方法不会尝试在运行时执行任何操作。编辑时间。

@willnationsdev我理解这是一个有效的解决方案(或解决我的问题的方法,因为我在写完原始评论后意识到第一种方法仍在工作。也就是说,我希望第二种方法能够得到适当的支持。我也想出了办法这可行:

DummySomeClass.gd
extends Node2D
class_name DummySomeClass

func foo():
    pass


SomeClass.gd
extends DummySomeClass
class_name SomeClass

func foo():
    for c in get_children() : 
        if c is DummySomeClass: 
            pass

话虽如此,我理解您对当前为何出现错误的解释。 对于此问题,有多种解决方案或变通办法,我认为这不是要解决的基本错误,但仍然是我希望将来某个时候看到的错误。

在稍微更复杂的用途中使用此方法后,这似乎会在其他耦合脚本的其他位置引起其他周期性错误,因此这可能不是解决问题的好方法。

这可能是一个幼稚的问题,但我们不应该摆脱这种非周期性的限制。
我的意思是其他语言(例如Java,C#,C ++等)可以处理类型而没有问题...

@harraps可以完成(正如我在线程中说过的几次),但是它需要对GDScript的连接方式进行一些根本性的更改。 由于我们即将发布,因此我现在不再赘述,并且此更改可能会破坏兼容性。

如果其他任何人遇到此问题,我发现了另一个与“循环引用”相关的错误的实例,但这与此处列出的其他实例不同。

如果使用静态工厂方法创建一个类,该类在返回值中引用当前类的名称,则它不会在编辑器内部报告任何错误,但是一旦关闭编辑器,您将收到错误报告资源仍在使用中。

extends Reference
class_name MyClass

static func make() -> MyClass:
    # can't even use get_script() for static funcs, but that's a separate issue
    var c = load("res://my_class.gd").new()
    return c

然后,您会收到此错误:

ERROR: SelfList<class GDScriptFunction>::List::~List: Condition ' _first != 0 ' is true.
   At: .......\godot\core/self_list.h:111
ERROR: SelfList<class GDScript>::List::~List: Condition ' _first != 0 ' is true.
   At: .......\godot\core/self_list.h:111
WARNING: ObjectDB::cleanup: ObjectDB Instances still exist!
     At: core\object.cpp:2093
Leaked instance: GDScript:17060 - Resource name:  Path: res://my_class.gd
Leaked instance: GDScriptNativeClass:1058
ERROR: ResourceCache::clear: Resources Still in use at Exit!
   At: core\resource.cpp:425

从#944转发,

我也经常遇到循环GDscript依赖项。 以下是一些我目前不得不恢复为无类型GDscript的用例:

  1. 我的角色使用ActorController ,它们运行不同的Move s(如状态机中的状态)。 ActorController转发_physics_process()然后转发到活动的Move 。 反之亦然,此举访问ActorController以切换到另一个Move或访问属性(如跳跃高度,运行速度等)

  2. 我的MoveRepository情况相同-存储库存储可重用的Move s,但是如果要获取另一个Move ,则Move s也需要访问存储库选择它到他们的ActorController

actor-framework

在C#或C ++中这不是问题,但是GDscript(具有可选的静态类型)要求我退回到变体(动态类型)或使用事件等创建不必要的间接调用。

我也有这个问题。 我有一个类似但更简单的设置。
TurnManager的变量类型Actor ,每个Actor都有对TurnManager的类型化引用。
我什is不使用
在Linux 64位上使用新的稳定版本3.1。

image

刚遇到这个。 似乎相关。

image

确实很奇怪。

image

我也似乎遇到了这种情况。 我想知道是否是因为脚本大多与对象分离? 我有一个扩展节点的基础属性类,并扩展了它的PrimaryAttribute和SecondaryAttribute,然后像12个PrimaryAttribute节点和SecondaryAttribute节点一样。 编辑器似乎不喜欢它吗? 即使我玩游戏时游戏运行正常。

值得注意的是,我切换了class_names的资源路径,这使事情在大约5分钟内可以正常工作,然后它们又无缘无故地给我错误。 :/

嗯错误似乎与在编辑器窗口中加载东西的顺序有关? 通过按它们继承的顺序关闭和重新打开文件,可以使它们消失。 因此,围绕它的某种麻烦可能是在某些文件中未声明内容。 :/

编辑:其实不,我打开文件的顺序无关紧要,即使我完全打开了其他文件也没关系。 当我第一次加载这些文件之一时,它们不会显示任何错误,并且直到我进行更改后才会显示所有错误。 :/

@ Angular-Angel我注意到重新启动Godot可以解决错误。 令人失望的是,我无法在Godot中使用带有自定义类/类型的静态类型,而不会弹出奇怪的错误。

“只要”关闭/重新打开项目就足够了。 Shift + Ctrl + Q(转到项目列表),确认提示,然后再次双击项目。 仍然有些令人沮丧,但是您已经习惯了(直到它被修复)。

抱歉,但是我也有点沮丧,由于你们发表评论,所以我不知道这种解决方法,我暂时停止输入代码,但是我还是很想念它。

同意对于我自己和其他人而言,这很快成为一个非常关键的习惯。 目前可能会看到重启解决方法是否足够。 (快速启动Godot会很棒)2019年5月16日上午8:27,里卡多·阿尔坎塔拉(Ricardo Alcantara) [email protected]写道:对不起,但我也有些沮丧,而且我不知道这种解决方法,因为你们评论了,我暂时停止输入代码了,但还是很想念它。

—收到评论是因为收到您的评论。直接回复此电子邮件,在GitHub上查看,或使该线程静音。

Godot 3.1.1(非单声道)
Stack.zip

最小的可复制示例

https://cdn.discordapp.com/attachments/477544613511692358/584811385838632977/unknown.png

_请_有人解决此问题。

image

加载正常,预加载不能

请注意,实际上在StackList.gd中存在未捕获的脚本错误。 具体来说,它是字典键声明中的语法错误。 但是,只有将字典更改为常量后才能捕获它。

只是想记一下我今天也遇到了“ is” class_name错误。

我已经恢复使用object.has_method(“ name”)而不是测试object是否为className

我在3.1.1中经常碰到这一点,并跳过篮球以避免出现这种情况。
希望它将在3.2中修复!

请不要在没有新信息的情况下碰碰问题。 我们都知道这种情况的发生,已经有很多例子,不会神奇地留下更多评论。

我目前正在尝试通过@JavaryGames修复此

我正在进行的修复仍然是WIP并导致崩溃。 我不确定在Beta阶段合并如此大的更改,因此稍后可能会在3.2.x版本中完成。

@vnen是否存在可修复此错误的分支,我们可以对其进行编译和测试?

不确定此时是否有更多信息有用,但是一种变通方法(对我有用

它发生在我更改了将变量强制转换为的类的方法的签名之后,立即使用as强制转换为类成员的那一行,但是在我确定实际方法之前。 然后,在修复方法之后,该行继续出现此错误,并且仅在我最终将强制转换类的名称更改为其他名称,然后再将其更改回时才停止。

@vnen是否存在可修复此错误的分支,我们可以对其进行编译和测试?

是的,我在公共分支中拥有它: https :

不确定此时是否有更多信息有用,但是一种变通方法(对我有用

您可能会在编辑器中得到一些缓存工件,因为在进行编辑时,所有内容一直都在重新加载。 但是,如果您遇到此问题,即使您设法在编辑器中实现无错误运行,它很可能在运行时也不起作用。

https://github.com/godotengine/godot/issues/38265似乎是对此的重复报告,其中包含一些复制细节。

此修复程序何时会出现在主线中?
这太烦人了,因为我使用类型保存脚本并且经常遇到此问题。
今天我遇到了无法解决的情况。

extends Resource
class_name WfcSlotHistory

func _init(slot:WfcSlot):
    pass
extends Resource
class_name WfcSlot

function saveHistory():
   var history:WfcSlotHistory = WfcSlotHistory.new(self)
   ...

res://assets/wfc/WfcSlotHistory.gd :5-解析错误:无法完全加载类“ WfcSlot”(脚本错误或循环依赖性)。
模块/ gdscript / gdscript。 cpp:576-方法失败。 返回:ERR_PARSE_ERROR

@MikeSchulze在这种情况下,我觉得部分原因是设计问题: WfcSlot可能不应该知道WfcSlotHistorysave操作应该在后者上。

(不过,这种行为/错误_is_令人讨厌,请不要误解我的意思。)

@ Jeto143感谢您的回复,我通过将所有Slot成员手动复制到SlotHistory中解决了我的问题。
希望这个错误将得到解决

嗨,开发人员,当这个长...长的bug最终会解决吗?

首先,我需要为一个类使用多个构造函数,但这是不允许的,但是为什么呢?
第二次尝试,我使用静态函数来解决此问题,但这也不起作用。

我有一个这样的课(简单的例子)
``
扩展资源
class_name ClassA

_init(valueA:int,valueB:int):
打印(值A,值B)

(value:int)-> ClassA的静态函数:
返回ClassA.new(值,值)
``

``
var o:ClassA = ClassA.new(1,2)#运行正常

var o2:ClassA = ClassA.of(2)#产生错误

``

使用静态功能会产生此错误。
“解析器错误:不允许在类文件中使用自己的名称(创建循环引用)”

因此,这阻碍了我编写一个类来使用多个构造函数,这些构造函数是现代语言中的标准行为。

我目前使用这样的hacky解决方法
```
(value:int)-> ClassA的静态函数:
var clazz = load(“ res://../../ClassA.gd”)
返回clazz.new(值,值)
``

最好的祝福
麦克风

嗨,开发人员,当这个长...长的bug最终会解决吗?

作为GDScript重写的一部分,它将在4.0中解决。

修复后,此功能是否也适用于静态功能?

class_name Cls

static func f():
    print(Cls)

@vnen,所以我们在3.2.X版本中,我们可以很快期望得到修复吗?

@ Ploppy3这些修复程序是由于GDScript重写所带来的巨大变化而导致的,因此可能无法进行选择。 如果要具有这些修复程序,则必须升级到4.0。

我也有这个问题,这是我的两个脚本。

class_name Entity extends Area2D

export var resource : Resource

onready var sprite   = get_node("sprite")
onready var collider = get_node("collider")

func _process(delta: float) -> void:
    if sprite   == null: sprite   = get_node("sprite")
    if collider == null: collider = get_node("collider")
    if resource is EntityConfig:
        sprite.frame = wrapf(sprite.frame+resource.gfx_speed, resource.gfx_start, resource.gfx_start+resource.gfx_count)
class_name EntityConfig extends Resource

export var gfx_image   := ""
export var gfx_start   := 0
export var gfx_speed   := 1.0
export var gfx_count   := 0
export var gfx_xoffset := 0.0
export var gfx_yoffset := 0.0
export var gfx_xsize   := 16.0
export var gfx_ysize   := 16.0
export var hit_xoffset := 0.0
export var hit_yoffset := 0.0
export var hit_xsize   := 16.0
export var hit_ysize   := 16.0

func new()->Area2D:
    var entity = Entity.new()
    entity.sprite            = Content.load_texture(gfx_image)
    if entity.sprite != null:
        entity.sprite.frame      = gfx_start
        entity.sprite.position.x = gfx_xoffset
        entity.sprite.position.y = gfx_yoffset
        entity.sprite.hframes    = entity.sprite.texture.get_width () / gfx_xsize
        entity.sprite.vframes    = entity.sprite.texture.get_height() / gfx_ysize

    entity.collider.position.x      = hit_xoffset
    entity.collider.position.y      = hit_yoffset
    entity.collider.shape.extents.x = hit_xsize / 2
    entity.collider.shape.extents.y = hit_ysize / 2
    return entity

我刚在Godot 3.2.3中完成顶点组项目时发现了这个问题。 对于我们的碰撞回调,我们有这样的东西:

extends Area2D

func _on_Throwable_body_entered(body: Node) -> void:
    if body is Player:
        if body.pick_up():
            queue_free()

因此,我们想在调用特定于Player的方法之前检查if body is Player 。 问题是,即使在全局范围内,无论是通过class_name还是通过preload -ed声明, Player可能也可能不可用。 即使Player没有预加载脚本以导致明显的循环依赖,也会发生这种情况。

目前,我们正在通过仅确保PlayerArea2D冲突掩码中的唯一内容而不根本不检查任何代码来解决此问题。 首先,我们正在检查if body.name == "player"

我很高兴得知它正在开发中,即使需要很长时间,我也希望一切顺利。

当我无法使用静态方法实现Builder模式时,我遇到了类似的依赖项问题:

class_name MyClass

static func build() -> MyClass:
  var new_instance  = MyClass.new()
  ...
  return new_instance

这里描述的从源文件路径加载类的解决方法很好,但是要求在不更改源代码的情况下不要更改文件树。

我使用此技巧即使在静态方法中也具有当前的源文件路径(在该方法中get_script()不可用):

static func build() :
    var new_instance = load(GodotExt.current_script_path()).new()
    ...
    return new_instance

class_name GodotExt

static func current_script_path():
    return get_stack()[1].source    <- return usable script path

这种获取当前课程的技巧似乎可以在任何地方使用。
它是原始的,可用于避免类似的循环依赖性问题等待全局依赖性修复。

@AliBouarab好招

此页面是否有帮助?
0 / 5 - 0 等级