Godot: Некоторые случаи использования class_name могут неожиданно вызывать циклические ошибки

Созданный на 26 авг. 2018  ·  69Комментарии  ·  Источник: godotengine/godot

64-разрядная версия Windows 10 - Godot 3.1 alpha

Изменить - доработана проблема, чтобы сосредоточиться на циклических ошибках.

Определенное использование class_name может приводить к циклическим ошибкам в ситуациях, когда нет циклических ссылок, и на самом деле иногда нет других ссылок, кроме одной данной.

Я чаще всего замечал это в скрипте инструмента при использовании is для сравнения классов, но, похоже, иногда это происходит в обычных ситуациях скрипта.

Мне не удалось воссоздать это в образце проекта.

godot master_2018-08-27_00-47-02

bug 3.2 confirmed high priority gdscript

Самый полезный комментарий

Исправление, над которым я работал, по-прежнему остается незавершенным и вызывает сбои. Я не уверен, что смогу объединить такое большое изменение на стадии бета-тестирования, поэтому, скорее всего, это будет сделано в выпуске 3.2.x позже.

Все 69 Комментарий

Это будет работать, если вы дадите базовому скрипту имя_класса и используете его в строке extends.
Я также получаю сообщение об ошибке при первом использовании имен файлов (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 например 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 Отлично , теперь я

@vnen Да, есть несколько дополнительных морщинок к рассказу. Позвольте мне посмотреть, насколько хорошо я могу их сформулировать.

Во-первых, решение Пита работает, когда базовому классу присваивается class_name все выглядит нормально. Я заметил, что если вернуться к базовому классу и вытащить class_name CustomBase который я добавил, он наполовину работает. Он больше не отображается в списке узлов при добавлении узлов, но is будет работать, и никаких странных ошибок.

Затем, чтобы подтвердить это, я воссоздал шаги по созданию расширенного скрипта base2.gd -> custom2.gd. Затем внутри custom.gd используйте class_name CustomClass2 , но без именования классов в базовом классе.

Возникла другая проблема. В списке узлов был первый узел, но он был отмечен значком «Ошибка».

godot master_2018-08-27_20-01-26

Итак, я изменил первый базовый класс, чтобы они оба использовали class_name . Но снова получил странные результаты.

Не все отображается в списке узлов, и тогда ключевое слово is вернуло истину только для одного из них. Хотя на этом снимке экрана вы можете видеть, что список узлов распознает CustomClass2, но в коде, стоящем за ним, is CustomClass2 возвращает false.

godot master_2018-08-27_20-05-11

Похоже, что многие вещи переключаются или остаются за кадром. Трудно предсказать, что он может делать с моими ограниченными знаниями.

Надеюсь, это поможет. ИКС)

редактировать игнорировать этот комментарий. Я не понимал, что class_name не реализовано в 3.0.6, эта проблема в любом случае относится к сборке 3,1.

class_name кажется неработающим в 3.0.6. Сделаю отдельный выпуск, но:

image

Классы сценариев

Я просто попробовал следующее, и каждая версия работала. Все классы скриптов появились в CreateDialog, скрипты скомпилированы нормально, сцена успешно запустилась и т. Д.

С такой иерархией сцен:

  • Узел (base.gd)

    • Узел (производный.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, тоже нет проблем.

Итак, есть ClassA, ClassB, ClassC. Если ClassC ссылается на ClassA с оператором is , то во время загрузки возникает ошибка. Если ClassC ссылается на ClassB, ошибки нет. Если ClassB ссылается на ClassA, ошибки нет.

Ни один из скриптов не находится в одной сцене, и все узлы являются братьями и сестрами (без родственных связей).

@AlexHolly То же самое и со мной сейчас. Кажется, что ошибка исчезла, но да, классы не будут отображаться в окне добавления узла, если у вас нет базового скрипта, который также использует class_name .

Это в альфе 3.1 c320d93

Небольшой пример с использованием «есть». То же самое может произойти, если вы используете «как».
Об этом тоже упомянул
cycle.zip

Ни один из скриптов не находится в одной сцене, и все узлы являются братьями и сестрами (без родственных связей).

Это не имеет ничего общего с узлами сцены. Циклы происходят в самом скрипте.

На данный момент довольно легко получить циклы при использовании is и as и если это произойдет, это не совсем ошибка, так оно и есть. Я постараюсь улучшить это, но не для 3.1. Исходный отчет является ошибкой, потому что в коде нет реальных циклов.

Не удалось воспроизвести ошибку и в 451e5fd. Узел не появился в окне создания, хотя.

Я могу подтвердить, что этой проблемы нет в 0dbe014 (последний удаленный мной мастер). Возможно, мы сможем закрыть эту проблему.

Кроме того, я смог сделать так, чтобы классы сценариев, расширяющие сценарии, по-прежнему отображались в CreateDialog, что по-прежнему было ошибкой. Связь с общественностью приведена выше.

@willnationsdev Спасибо, Уилл. X) Я сталкивался с различными проблемами с class_name , но не смог воссоздать эту. Их было ужасно сложно воссоздать, но с тех пор я перестал их использовать.

Я заметил, что иногда в сценарии могут появляться расплывчатые и не связанные с этим ошибки из-за ошибок в сценарии, на который ссылаются. Они становятся более значимыми при открытии сценария виновника, а после исправления эти другие также исчезают.

Тем не менее, я изменю тему сообщения, потому что эта циклическая ошибка, похоже, все еще возникает в странных ситуациях и неуловима при попытке ее воссоздать. Так что, наверное, еще что-то есть, я оставлю это для внен.

@avencherus Понятно . Что ж, надеюсь, вы со временем сможете определить, в каких условиях это происходит. Без контекста мы не можем это исправить. XD

Я заметил несколько циклических ошибок ссылок, которые произошли в моей работе godot-next, где я мог использовать статическую типизацию, чтобы сказать, что я возвращаю тот же тип, что и имя класса скрипта, но если я попытался фактически сослаться на имя класса сценария (чтобы создать экземпляр для последующего возврата в функцию), это не сработает, потому что сценарий будет ссылаться на себя и, следовательно, должен будет бесконечно рекурсивно загружать себя.

Решение, которое я нашел, заключалось в использовании load(get_script().resource_path).new() . Я знаю, что это довольно сложно, но это позволило синтаксическому анализатору безопасно построить данные и безопасно пройти процесс компиляции, позволить типу официально зарегистрировать, а затем ссылаться на тип только в RUNTIME после его полной инициализации.

Я буду периодически продолжать попытки дразнить это. Хотелось бы мне помочь, но я представляю, что им придется подождать, пока те, кто глубоко знаком с их реализацией, не будут работать над своими собственными проектами, и сначала столкнутся с этими проблемами. Держу пари, они знают, на что обратить внимание в этой ситуации.

Краткое изложение некоторых проблем (я опубликую их в ближайшие недели):

  1. Я получал эти циклические ошибки при выполнении obj is MyClass и между ними не было другой связи или ссылки. Хотя я не знаю, сканирует ли он дерево сцены и считает ли его дочерние элементы циклическими ссылками.
  2. Я также столкнулся с описанными вами неудобствами. Я бы хотел, чтобы это было не так, потому что он отлично работает с именами встроенных / собственных классов в тех же типах ситуаций. Таким образом, вы можете написать целую кучу кода с этой конечной целью, думая, что все в порядке, пока вы не начнете добавлять свои пользовательские типы, и вам придется прибегнуть к методам взлома / обходного пути / старому, а затем то, что было значение этого, если не избегать подробных имен путей?
  3. У меня эти вещи были безошибочными в редакторе и выполнялись без ошибок во время тестовых прогонов, но затем продолжались ошибки и сбои в экспортированной игре. Пример ниже (хотя, скорее всего, не связанный с этой проблемой): использование class_name не может найти свои значки в сборке, но никаких проблем при прогонах и тестах из редактора.

gtc_2018-10-12_13-21-35

В целом мой опыт работы с class_name был почти ежедневным, когда я сталкивался с множеством непредсказуемых, трудно объяснимых и трудно воспроизводимых ошибок. Много времени тратится впустую, танцуя вокруг этого и пытаясь решить их.

Я очень ждал их, и они определенно сделают кодирование некоторых вещей намного более компактным и читаемым. По практическим соображениям времени я должен отложить их в сторону и отказаться от их использования в моем текущем проекте.

Может быть, в 4.0. ИКС)

Я собираюсь вернуться к старому методу путей скриптов. При этом я бы предпочел использовать их полностью, чтобы избежать случайных class_name сюрпризов и чтобы код был более согласованным.

Как я сказал ранее, очень легко создавать циклы с помощью class_name , особенно при использовании is и as . С путями это не так просто, но вы можете столкнуться с аналогичными проблемами. Проблема в том, что GDScript никогда не был настроен на такую ​​работу, поэтому он слишком сильно зависит от загрузки ресурсов. У меня есть некоторые идеи, чтобы исправить это (в частности, просто игнорировать загрузку ресурсов и выполнять неглубокий анализ зависимостей напрямую), но это требует структурного изменения парсера.

Возможно, в следующих версиях она будет решена должным образом, так как сейчас не время возиться с этим. class_name пока будет "меньшей функцией". Вы все еще можете использовать его в некоторых случаях, но не так широко, как вы ожидаете.

@vnen Привет. Добро пожаловать. ИКС)

Спасибо за ответ и сроки.

Ага, вот почему я должен пока отложить это. Я не сразу понял, что это не такая гладкая, подходящая или естественная интеграция. (Я как бы намекал на это, когда увидел все записи в файле проекта.)

Я полагаю, это кажется «второстепенной» функцией, но она будет иметь очень серьезные преимущества, если удастся устранить морщины. Я действительно с нетерпением жду этого и чувствую его потерю после того, как уже использовал его. Это определенно хороший путь для 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 s также должны иметь доступ к репозиторию, если они хотят получить еще один Move выбрать его в свои ActorController

actor-framework

Это не проблема для C # или C ++, но GDscript (с необязательной статической типизацией) требует, чтобы я возвращался к вариантам (динамическая типизация) или создавал ненужные косвенные ссылки с использованием событий и т. Д.

У меня тоже такая проблема. У меня есть аналогичная, но более простая установка.
Класс TurnManager имеет переменную типа Actor и каждый Actor имеет типизированную ссылку на TurnManager
Я даже не использую is Я буквально только что объявил переменные, и этого достаточно, чтобы спровоцировать эту ошибку.
Использование новой стабильной версии 3.1 в 64-битной Linux.

image

Просто столкнулся с этим. Кажется связанным.

image

Действительно, очень странно.

image

Я тоже, кажется, сталкиваюсь с этим. Мне было интересно, не потому ли, что у меня скрипты в основном были отделены от объектов? У меня есть базовый класс Attribute, который расширяет узел, и PrimaryAttribute и SecondaryAttribute, расширяющие его, а затем как 12 узлов PrimaryAttribute и узел SecondaryAttribute. Редактору, кажется, это не нравится? Хотя игра работает нормально, когда я в нее играю.

Следует отметить, что я отключил пути к ресурсам для class_names, и все работало нормально около 5 минут, прежде чем они вернулись к выдаче ошибок без причины. : /

Хм. Ошибки, похоже, связаны с порядком загрузки вещей в окне редактора? Я могу заставить их уйти, закрыв и снова открыв файлы в том порядке, в котором они унаследованы. Так что, вероятно, какая-то проблема с тем, что он не объявляет что-то в некоторых файлах. : /

Изменить: на самом деле нет, не имеет значения, в каком порядке я открываю файлы или даже если у меня вообще открыты другие файлы. Когда я впервые загружаю один из этих файлов, они не показывают никаких ошибок, и не будут, пока я их не изменю, а затем все ошибки не появятся. : /

@ Angular-Angel Я заметил, что перезапуск Godot устраняет ошибки. Прискорбно, что я не могу использовать статическую типизацию в Godot с настраиваемыми классами / типами, но без появления странных ошибок.

«Просто» закрытие / повторное открытие проекта было для меня достаточно. Shift + Ctrl + Q (перейти к списку проектов), подтвердить запрос, затем снова дважды щелкнуть проект. Все еще немного расстраивает, но к этому привыкаешь (пока не исправишь).

Извините, но я тоже немного разочарован, и я не знал об этом обходном пути, так как вы, ребята, прокомментировали, я перестал печатать свой код некоторое время, но я все еще скучаю по нему ОЧЕНЬ.

Согласовано. Это очень быстро стало ключевой привычкой для меня и других. Вероятно, посмотрим, достаточно ли на данный момент обходного пути перезапуска. (Годо запускается быстро, будет здорово) 16 мая 2019 г., 8:27, Рикардо Алькантара [email protected] написал: Извините , но я тоже немного разочарован, и я не знал об этом обходном пути, так как вы, ребята, прокомментировали , Я какое-то время перестал набирать код, но все еще ОЧЕНЬ скучаю по нему.

- Вы получили это, потому что прокомментировали. Ответьте на это письмо напрямую, просмотрите его на GitHub или отключите обсуждение.

Годо 3.1.1 (не моно)
Stack.zip

минимальный воспроизводимый пример

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

_please_ кто-нибудь исправит это.

image

загрузка работает нормально, предварительная загрузка - нет

Обратите внимание, что на самом деле в StackList.gd есть неперехваченная ошибка сценария. В частности, это синтаксическая ошибка в объявлении ключа словаря. Однако он обнаруживается только после того, как словарь изменяется на константу.

Просто хотел отметить, что сегодня я тоже столкнулся с ошибкой "is" class_name.

Я вернулся к использованию object.has_method ("name"), а не к проверке, является ли объект className

Я часто попадал в него в 3.1.1 и прыгал через обручи, чтобы его избежать.
Надеюсь, это будет исправлено в версии 3.2!

Прошу не выдвигать вопросы без новой информации. Мы все знаем, что это происходит, у нас уже есть много примеров, и мы не уйдем волшебным образом с новыми комментариями.

В настоящее время я пытаюсь исправить это на @JavaryGames , решение уже работает. Не уверен, войдет ли он в 3.2, поскольку это большое изменение (пришлось несколько переделать внутреннюю работу GDScript), и мы близки к выпуску, но, возможно, мы сможем интегрировать в 3.2.1 или что-то в этом роде. Обязательно исправят в 4.0.

Исправление, над которым я работал, по-прежнему остается незавершенным и вызывает сбои. Я не уверен, что смогу объединить такое большое изменение на стадии бета-тестирования, поэтому, скорее всего, это будет сделано в выпуске 3.2.x позже.

@vnen Есть ли ветка с исправлением этой ошибки, которую мы можем скомпилировать и протестировать?

Не уверен, что дополнительная информация на данный момент поможет, но обходной путь (который сработал для меня) - изменить class_name проблемного класса, а затем вернуть его обратно. Кажется, что это связано с кешем.

Это случилось со мной в строке, где я приводил член класса с помощью as сразу после изменения сигнатуры метода класса, к которому была приведена переменная, но до того, как я смог исправить фактический метод. Затем, после исправления метода, строка продолжала выдавать эту ошибку, и она остановилась только тогда, когда я наконец изменил имя класса приведения на что-то другое, а затем снова изменил его.

@vnen Есть ли ветка с исправлением этой ошибки, которую мы можем скомпилировать и протестировать?

Да, у меня он есть в моем публичном форке: https://github.com/vnen/godot/commit/gdscript-no-cycles

Не уверен, что дополнительная информация на данный момент поможет, но обходной путь (который сработал для меня) - изменить class_name проблемного класса, а затем вернуть его обратно. Кажется, что это связано с кешем.

Вы можете получить некоторые артефакты кеширования в редакторе, так как все постоянно перезагружается во время редактирования. Но если вы столкнетесь с этой проблемой, она, скорее всего, не будет работать во время работы, даже если вам удастся исправить ее в редакторе.

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 вероятно, не должен знать о WfcSlotHistory . Действие save вероятно, должно быть на последнем.

(Это поведение / ошибка _из_ раздражает, не поймите меня неправильно.)

@ Jeto143, спасибо за ваш ответ, я решил свою проблему, скопировав вручную всех участников Slot в SlotHistory.
Надеюсь, этот баг будет исправлен

Привет, разработчики, когда эта долгая ... долгая ошибка будет наконец решена?

Сначала мне нужно несколько конструкторов для класса, но это недопустимо, но почему?
Во второй попытке я использую статическую функцию для решения этой проблемы, но это тоже не работает.

У меня есть такой класс (простой пример)
`` ''
расширяет ресурс
имя_класса ClassA

_init (значениеA: int, значениеB: int):
печатает (значениеA, значениеB)

статическая функция (значение: int) -> ClassA:
return ClassA.new (значение, значение)
`` ''

`` ''
var o: ClassA = ClassA.new (1,2) # работает нормально

var o2: ClassA = ClassA.of (2) # выдает ошибку

`` ''

Эта ошибка возникает при использовании статической функции.
«Ошибка парсера: использование собственного имени в файле класса недопустимо (создает циклическую ссылку)»

Таким образом, я не могу написать класс для использования нескольких конструкторов со стандартным поведением в современных языках.

Я использую текущий обходной путь вроде этого
``
статическая функция (значение: int) -> ClassA:
var clazz = load ("res: //../../ClassA.gd")
return clazz.new (значение, значение)
`` ''

С уважением
Майк

Привет, разработчики, когда эта долгая ... долгая ошибка будет наконец решена?

Это будет решено в 4.0 как часть перезаписи GDScript.

Будет ли это работать и для статических функций после исправления?

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

Я только что обнаружил эту проблему во время работы над своим групповым проектом Capstone в Godot 3.2.3. Для наших обратных вызовов столкновений у нас есть что-то вроде этого:

extends Area2D

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

Итак, мы хотим проверить if body is Player перед вызовом методов, специфичных для игрока. Проблема в том, что Player может быть или не быть доступным, даже если он находится в глобальной области, независимо от того, объявлен ли он через class_name или preload -ed. Это происходит, даже если Player не предварительно загружает наш скрипт, чтобы вызвать очевидную циклическую зависимость.

В настоящее время мы работаем над этим, просто гарантируя, что Player - единственное, что есть в маске столкновения Area2D и вообще ничего не проверяем в коде. Сначала мы проверяли 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 рейтинги