Godot: Alguns usos de `class_name` podem produzir erros cíclicos inesperadamente

Criado em 26 ago. 2018  ·  69Comentários  ·  Fonte: godotengine/godot

Windows 10 de 64 bits - Godot 3.1 alfa

Editar - problema refinado para enfocar erros cíclicos.

Certos usos de class_name podem produzir erros cíclicos em situações onde não há referências cíclicas e, de fato, às vezes, nenhuma outra referência fora da única dada.

Percebi isso com mais frequência no script de ferramenta ao usar is para fazer uma comparação de classe, mas parece acontecer às vezes em situações normais de script.

Recriá-lo em um projeto de amostra me iludiu.

godot master_2018-08-27_00-47-02

bug 3.2 confirmed high priority gdscript

Comentários muito úteis

A correção em que estava trabalhando ainda é o WIP e está causando travamentos. Não estou confiante para mesclar uma mudança tão grande no estágio beta, então provavelmente será feito em uma versão 3.2.x mais tarde.

Todos 69 comentários

Funcionará se você der ao script base um class_name e usá-lo na linha extends.
Também estou recebendo o erro ao usar nomes de arquivo no início (https://github.com/godotengine/godot/blob/master/modules/gdscript/gdscript_parser.cpp#L4947), mas também desaparece e não aparece depois de ter funcionado uma vez (como em, depois de usar a solução alternativa mencionada)

@ PetePete1984 Legal, obrigado Pete. É assim que se pretende usar então?

Enquanto verificava e testava isso, estava olhando para o método get_class() e me perguntando se ele deveria retornar Node2D. A parte is CustomClass está retornando _verdadeira_, mas is_class("CustomClass") por outro lado é _false_.

CC @reduz @vnen @willnationsdev

Eu não diria que é um comportamento intencional, especialmente não com uma mensagem de erro que implica inclusões cíclicas onde não há.
get_class() e is_class() são confusos para mim em geral, não posso comentar sobre isso. A fonte pode resolver esse mistério no longo prazo, mas até agora is tem sido o suficiente para mim.

@vnen Seria algo que precisa de uma mensagem de erro mais clara?

@ PetePete1984 Sim, is tem sido uma coisa incrível agora no 3.1. Embora eu tenha encontrado uma situação em que gostaria de usar o novo match como match custom_thing.get_class() e comparar com várias strings. Mas nada crítico, apenas legibilidade e menos coisa de digitação.

@avencherus Você pode conseguir se safar com:

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

Não sei por que está apresentando esse erro, terei que investigar.

@willnationsdev Não tenho certeza de qual é o cheque da parte get_script() , pelo menos para mim, ele retorna um objeto GDScript [GDScript:1057] .

@vnen Obrigado vnen. X) Algumas outras coisas estranhas parecem estar acontecendo quando voltei para experimentar essas sugestões para ver se eu poderia lhe dar alguma informação melhor. Vou puxar, reconstruir e mexer nele um pouco. Veja se há algo mais a acrescentar. Posso ter encontrado um problema diferente ao longo do caminho.

@avencherus os "nomes de classe" das classes de script são variáveis ​​globais que fazem referência ao script. Então...

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

@willnationsdev Oh legal, entendo agora. Eu não esperava que class_name funcionasse assim, ou que o tipo personalizado estivesse disponível para o padrão de correspondência. Obrigado por compartilhar esta dica Will.

@vnen Sim, algumas rugas adicionais para a história. Deixe-me ver como posso articulá-los bem.

Em primeiro lugar, a solução de Pete funciona, quando uma classe base recebe class_name tudo parece bem. O que percebi é que, voltando para a classe base e retirando o class_name CustomBase que adicionei, meio que funciona. Ele não aparece mais na lista de nós ao adicionar nós, mas is funcionará, e sem erros estranhos.

Então, para confirmar isso, recriei as etapas de criação de um script estendido base2.gd -> custom2.gd. Então, dentro de custom.gd, use class_name CustomClass2 , mas sem nomeação de classe na classe base.

Outro problema apareceu. A lista de nós tinha o primeiro, mas listada com um ícone que dizia "Erro"

godot master_2018-08-27_20-01-26

Então eu modifiquei a primeira classe base para que ambas usassem class_name . Mas obteve resultados estranhos novamente.

Nem tudo está aparecendo na lista de nós, e então a palavra-chave is só retornou verdadeiro para um deles. Embora nesta captura de tela você possa ver que a lista de nós reconhece CustomClass2, no código por trás dela, is CustomClass2 está retornando falso.

godot master_2018-08-27_20-05-11

Parece que muitas coisas estão mudando ou demorando nos bastidores. É difícil prever o que pode estar fazendo com meu conhecimento limitado.

Espero que ajude. X)

editar desconsiderar este comentário. Eu não tinha percebido que class_name não está implementado no 3.0.6, este problema se refere a uma compilação 3,1 de qualquer maneira.

class_name parece estar quebrado no 3.0.6. Vou fazer um problema separado, mas:

image

As classes de script

Eu apenas tentei o seguinte e cada versão funcionou. Todas as classes de script apareceram no CreateDialog, os scripts foram compilados corretamente, a cena foi executada com sucesso, etc.

Com uma hierarquia de cenas como esta:

  • Nó (base.gd)

    • Nó (derivado.gd)

Roteiro:

# 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")

Cada vez que eu fazia o teste, ele imprimia

base
derived
base

...Como deveria.

Minha sugestão seria tentar limpar o cache de arquivo de seu editor (se talvez houvesse mudanças na maneira como o cache de arquivo foi armazenado no meio de sua programação / atualização do mecanismo, isso poderia de alguma forma bagunçar as coisas até que você o limpe).

@willnationsdev Obrigado por olhar, vou tentar fazer isso. Estes são os arquivos da pasta AppData / Roaming? Vou prosseguir e limpar tudo por enquanto. Em caso afirmativo, está se perguntando se há algo mais específico que devo excluir?

@avencherus Não tenho certeza. Acabei de me lembrar de @karroffel mencionando algo sobre isso quando acrescentei algumas correções ao ícone da classe de script anteriormente.

Testado em https://github.com/godotengine/godot/commit/1093c0ff51b980634dffdd9618eaa53061da6419
Não vejo nenhum erro, mas não está mostrando o Nó na caixa de diálogo "Criar novo Nó".

Também estou recebendo o erro mostrado na postagem original (Windows x64 Godot 3.1 alpha):

image

No entanto, isso acontece em um contexto diferente. Eu tenho 3 scripts, cada um com um class_name e cada um deles estende o Node2D. O erro não ocorre a menos que um dos scripts faça referência a ele com o operador is . Por exemplo if some_var is Incomer . O estranho, porém, é que se o mesmo script fizer referência ao outro class_name, não haverá problema. E se o outro script fizer referência ao class_name em questão, também não há problema.

Portanto, há uma ClassA, ClassB, ClassC. Se ClassC referenciar ClassA com o operador is , ocorrerá um erro no momento do carregamento. Se ClassC faz referência a ClassB, não há erro. Se ClassB faz referência a ClassA, não há erro.

Nenhum dos scripts está na mesma cena e todos os nós são irmãos (sem relacionamento de ancestral).

@AlexHolly A mesma situação comigo agora também. O erro parece ter desaparecido, mas sim, as classes não aparecerão na janela de adicionar nó quando não houver um script de base que também use class_name .

Isso está em alfa 3.1 c320d93

Um pequeno exemplo usando "é". A mesma coisa pode acontecer se você usar "como".
Isso também foi mencionado por @Oranjoose .
ciclo.zip

Nenhum dos scripts está na mesma cena e todos os nós são irmãos (sem relacionamento de ancestral).

Isso não tem nada a ver com os nós da cena. Os ciclos acontecem no próprio script.

Por enquanto é muito fácil obter ciclos ao usar is e as e se isso acontecer não é realmente um bug, é do jeito que é. Vou tentar melhorar isso, mas não para 3.1. O relatório original é um bug porque não há ciclos reais no código.

Não consegui reproduzir o erro em 451e5fd também. O nó não apareceu na janela de criação embora.

Posso confirmar que este problema não está presente em 0dbe014 (o último master que puxei). Provavelmente podemos encerrar este problema.

Além disso, consegui fazer com que as classes de script que estendem os scripts ainda apareçam no CreateDialog, o que ainda era um bug. PR está vinculado acima.

@willnationsdev Obrigado, Will. X) Tenho encontrado vários problemas com class_name , mas não consegui recriar este. Eles são terrivelmente difíceis de recriar, mas desde então parei de usá-los.

Percebi que às vezes podem aparecer erros vagos e não relacionados em um script, devido a erros em um script que está sendo referenciado. Eles se tornam mais significativos ao abrir o script do culpado e, quando corrigidos, esses outros também são eliminados.

No entanto, vou refazer o tópico da postagem, porque esse erro cíclico parece ainda estar acontecendo em situações estranhas e é evasivo ao tentar recriá-lo. Portanto, provavelmente ainda há algo a fazer, vou deixá-lo aberto para vnen.

@avencherus entendo. Bem, espero que você possa eventualmente identificar em que condições isso está acontecendo. Sem o contexto, não podemos consertar. XD

Eu notei alguns erros de referência cíclica que aconteceram em meu trabalho godot-next, onde fui capaz de usar a digitação estática para dizer que estava retornando o mesmo tipo que o nome da classe do script, mas se eu tentasse realmente fazer referência ao nome da classe do script (para criar uma instância para retornar posteriormente na função), não funcionaria porque o script estaria se referenciando a si mesmo e, portanto, precisaria se carregar recursivamente infinitamente.

A solução que encontrei foi usar load(get_script().resource_path).new() . Bastante boca cheia, eu sei, mas permitiu ao analisador construir os dados com segurança e passar pelo processo de compilação com segurança, deixar o nome de tipo ser oficialmente registrado e, então, apenas fazer referência ao tipo em RUNTIME depois de ter sido completamente inicializado.

Vou continuar fazendo um esforço periódico para descobri-lo. Gostaria de poder ajudar mais, mas estou imaginando que eles terão que esperar até que aqueles com profundo conhecimento de sua implementação estejam trabalhando em seus próprios projetos e se deparem com esses problemas. Eu apostaria que eles saberiam onde colocar seus olhos nessa situação.

Um rápido resumo de alguns dos problemas (postarei isso nas próximas semanas):

  1. Eu recebia esses erros cíclicos ao fazer obj is MyClass e não havia nenhuma outra conexão ou referência entre os dois. Embora eu não saiba se ele está escaneando a árvore da cena e contando seus filhos como referências cíclicas.
  2. Também encontrei o inconveniente que você descreveu. Eu gostaria que não fosse assim, porque funciona bem com nomes de classes nativas / integradas nos mesmos tipos de situações. Então você pode escrever um monte de código com esse objetivo final em mente pensando que está tudo bem, até que você comece a adicionar seus tipos personalizados, e você tenha que recorrer a um método hack / work-around / mais antigo, e então o que foi o valor disso senão para evitar nomes de caminho detalhados?
  3. Eu tive essas coisas sem erros no editor e executando limpo durante as execuções de teste, mas depois continuo tendo erros e falhas no jogo exportado. Um exemplo abaixo (embora provavelmente não relacionado a este problema) é que o uso de class_name não conseguiu encontrar seus ícones na construção, mas não há problemas em execuções e testes do editor.

gtc_2018-10-12_13-21-35

No geral, minhas experiências com class_name têm sido um encontro quase diário com muitos erros imprevisíveis, difíceis de explicar e difíceis de reproduzir. Muito tempo é perdido dançando em torno disso e tentando resolvê-los.

Eu estava realmente ansioso por eles, e eles certamente tornariam a codificação de certas coisas muito mais compactas e legíveis. Por motivos práticos de tempo, tenho que colocá-los de lado e optar por não usá-los em meu projeto atual.

Talvez em 4.0. X)

Vou voltar ao antigo método de caminhos de script. Ao fazer isso, seria apenas minha preferência usá-los totalmente para evitar qualquer surpresa class_name aleatória e para manter o código mais consistente.

Como eu disse antes, é muito fácil criar ciclos com class_name , especialmente ao usar is e as . É menos fácil com caminhos, mas você também pode encontrar problemas semelhantes. O problema é que o GDScript nunca foi programado para funcionar assim, então depende muito do carregamento de recursos. Tenho algumas ideias para corrigir isso (em particular, apenas ignorar o carregamento de recursos e fazer uma análise superficial das dependências diretamente), mas isso requer uma mudança estrutural do analisador.

Provavelmente será resolvido de forma adequada nas próximas versões, já que não é um bom momento para mexer com isso. class_name será um "recurso menor" por enquanto. Você ainda pode usá-lo em alguns casos, mas não tão extensivamente quanto você espera.

@vnen Hey. Bem vindo de volta. X)

Obrigado pela resposta e pelo cronograma.

Sim, é por isso que tenho que guardá-lo por agora. Demorei um pouco para perceber que não era uma integração tão suave, adequada ou natural. (Eu estava tendo dicas disso quando vi todas as entradas no arquivo do projeto.)

Suponho que pareça uma característica "menor", mas terá alguns benefícios muito sérios se as rugas puderem ser resolvidas. Eu realmente estou ansioso por isso e sinto sua perda depois de já usá-lo um pouco. É definitivamente um bom caminho a seguir para GDScript.

Uma coisa importante que perderei é a capacidade de recorrer a dicas quando uma classe personalizada é combinada com seu novo tipo de dicas. var thing : NewThing

Ao fazer uma grande classe em alguns dias, e talvez alguns dias depois, a primeira vez que usá-la surge, acho que não me lembro 100% dos nomes precisamente de todas as funções até que as usei algumas vezes. Portanto, receber essas dicas foi um salto de produtividade bastante inesperado e significativo para mim. Pude ficar e trabalhar em uma área por muito mais tempo.

Certamente, o cerne da questão é, como você diz, ciclos fáceis, mas acho que minhas piores experiências foram que atualmente alguns dos erros não estão apontando para os lugares certos. Já se passaram algumas semanas, mas já tive situações em que usei uma aula personalizada e tudo estava bem por alguns dias. Em seguida, escrevi mais um código que chamava essa classe personalizada e, em algum ponto durante o desenvolvimento, comecei a receber os erros de ciclo. Em alguns casos, esses erros não foram úteis para explicar onde o erro estava ocorrendo. Para encontrá-lo, tive que procurar e remover todos os usos de nomes de classes, um por um, até que o erro parasse.

Apenas alguns incidentes como esse recuperaram grande parte dos ganhos. Tenho medo de imaginar o surgimento de um problema como esse em algum lugar com 30.000 linhas.

O único incidente que me fez arrancar todos eles foi aquele em que os erros de ciclo só apareciam na compilação de exportação e geravam erros de script não relacionados. Acho que alguém estava dizendo que as texturas do ícone não foram encontradas, mas realmente não era isso, e isso ficou claro quando eu abandonei alguns usos de class_name. Suspeito que class_name estava falhando e o erro estava caindo na linha a seguir.

Já vi isso acontecer às vezes quando os erros acontecem na linha acima ou abaixo da causa.

É muito difícil para mim e meu conhecimento zero aqui localizar a origem de muitos desses problemas. Muito disso está simplesmente atrás da cortina para mim, e estou grato por você ser capaz de decifrar parte disso.

No 3.1 houve muitos eventos incomuns com os avisos e erros, então fico imaginando se o problema é a coisa em si ou um problema com a lógica de relatório de erros. Ainda não sei exatamente por onde começar, e só posso esperar que parte disso acabe sendo útil e também com o tempo que eu possa restringi-los em pequenos projetos.

EDIT: Esqueça, de alguma forma, acabei de resolver a inclusão cíclica simplesmente por não fazê-lo ...
As classes globais em project.godot são sobrescritas de qualquer maneira ao iniciar o editor.

@vnen ou @avencherus Seria bom atualizar o OP com uma descrição clara do que é esse bug no final, pois caso contrário, é uma longa discussão para ler antes de ter uma boa ideia a respeito.

@ akien-mga Não tenho mais certeza sobre seu status, ou o que escrever sobre ele.

Se bem me lembro, há pelo menos algumas partes. Os erros cíclicos esperados como uma limitação do GDScript em sua forma atual, e depois os inesperados que aparecem, são difíceis de isolar e reproduzir em pequenos projetos (às vezes por causa de mensagens de erro imprecisas).

Como não é um recurso que estou usando no momento, não tenho acompanhado o progresso. Acho que algumas coisas aqui e ali foram consertadas desde então.

Diante dessas outras questões, parece que a conversa é sobre as mudanças necessárias no GDScript. Com as revisões destinadas a 3.2. Se esse for o plano, então não estaria mais no marco 3.1.

Provavelmente não há problema em fechá-lo, a menos que vnen o esteja usando para contabilidade ou se você preferir usá-lo como referência para os próximos problemas de duplicação quando 3.1.0 estabilizar.

O recurso é uma vantagem de usabilidade em que estou interessado, então provavelmente irei revisitá-lo no 3.2 e postar qualquer descoberta.

Bem, isso não deve ser fechado, não, a grande quantidade de relatórios duplicados definitivamente mostra que há algo para consertar :)

Encontrei a seguinte mensagem de erro que é problemática para mim ao atualizar um projeto de 3.0 para 3.1. Anteriormente, o seguinte código funcionava:

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()

Quando eu mudo o código para:

extends Node2D
class_name SomeClass

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

Eu obtenho o seguinte erro:

Erro de análise: o uso de um nome no arquivo de classe não é permitido (cria uma referência cíclica)

Isso é frustrante para mim, pois todos os nós filhos que procuro herdam desta classe e estão misturados com outros nós filhos que não. É a capacidade de digitar verificar outras instâncias de uma classe de script que não funcione dessa maneira e há outra maneira que eu deveria fazer isso.

@Diaspater Acho que tudo o que você precisa fazer é mudar if c is SomeClass para if c is get_script() . Ambas as opções executam uma verificação de tempo de execução, mas a versão SomeClass requer que você carregue o script novamente na hora do editor (resultando em uma referência cíclica) enquanto o método get_script() não tenta fazer nada em tempo do editor.

@willnationsdev Eu entendo que é uma solução válida (ou uma solução alternativa para o meu problema, como percebi depois de escrever meu comentário original que a primeira maneira ainda está funcionando. Dito isso, eu preferiria que a segunda maneira pudesse ser devidamente suportada. Também descobri que isso funciona:

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

Dito isso, entendo sua explicação de por que ele está apresentando um erro. Com várias soluções ou soluções alternativas para este problema, sinto que este não é um bug essencial para corrigir, mas ainda é um bug que gostaria de ver corrigido em algum momento no futuro.

Depois de usar esse método em usos um pouco mais complexos, parece que isso está causando outros erros cíclicos em outros locais em outros scripts acoplados, portanto, provavelmente não é uma boa solução / solução alternativa para o problema.

Esta pode ser uma pergunta ingênua, mas não deveríamos nos livrar dessa restrição não cíclica?
Quero dizer, outras linguagens como Java, C #, C ++, etc ... podem lidar com tipos sem problemas ...

@harraps isso será feito (como eu disse algumas vezes no tópico), mas requer algumas mudanças fundamentais em como o GDScript é conectado. Não vou tocar nisso agora, pois estamos próximos do lançamento e essa mudança provavelmente quebrará a compatibilidade.

Caso qualquer outra pessoa encontre isso, eu encontrei outra instância de erro relacionado a "referência cíclica", mas é diferente das outras listadas aqui.

Se você fizer uma classe com um método de fábrica estático que faz referência ao nome da classe atual no valor de retorno, ele não relatará nenhum tipo de erro dentro do próprio editor, mas quando o editor fechar, você obterá um relatório de erro que os recursos ainda estão sendo usados.

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

Você obterá então este erro:

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

Repostagem de # 944,

Também estou encontrando dependências GDscript cíclicas regularmente. Aqui estão alguns casos de uso em que sou forçado a reverter para GDscript não digitado:

  1. Meus personagens usam um ActorController que executa Move s diferentes (como estados em uma máquina de estado). O ActorController encaminha _physics_process() e assim para o Move ativo. Vice-versa, o movimento acessa ActorController para mudar para outro Move ou propriedades de acesso (como altura do salto, velocidade de corrida, etc.)

  2. Mesma situação com meu MoveRepository - o repositório armazena Move s reutilizáveis, mas os Move s também precisam acessar o repositório se quiserem buscar outro Move para selecioná-lo em seus ActorController

actor-framework

Isso não é um problema em C # ou C ++, mas GDscript (com tipagem estática opcional) requer que eu recue para variantes (tipagem dinâmica) ou crie caminhos indiretos desnecessários usando eventos e outros.

Eu também estou tendo esse problema. Tenho uma configuração semelhante, mas mais simples.
A classe TurnManager tem uma variável do tipo Actor e cada Actor tem uma referência digitada ao TurnManager
Eu nem estou usando is Eu literalmente declarei as variáveis ​​e é o suficiente para provocar este erro.
Usando a nova versão estável 3.1 no Linux de 64 bits.

image

Apenas corri para isso. Parece relacionado.

image

Muito estranho mesmo.

image

Eu também pareço estar enfrentando isso. Eu queria saber se é porque eu tinha os scripts principalmente separados dos objetos. Eu tenho uma classe de atributo base, que estende o nó, e PrimaryAttribute e SecondaryAttribute estendendo-o, e então, como 12 nós PrimaryAttribute e um nó SecondaryAttribute. O editor não parece gostar? Mesmo que o jogo corra bem quando eu o jogo.

É importante ressaltar que eu mudei os caminhos de recursos para class_names, e isso fez as coisas funcionarem bem por cerca de 5 minutos antes de voltarem a me fornecer erros sem motivo. : /

Hmm. Os erros parecem ter a ver com a ordem em que as coisas são carregadas na janela do editor? Posso fazer com que eles desapareçam fechando e reabrindo os arquivos na ordem em que são herdados. Então, provavelmente algum tipo de problema em torno dele não declarar coisas em alguns arquivos. : /

Editar: Na verdade não, não importa a ordem em que eu abro os arquivos, ou mesmo se eu tenho outros arquivos abertos. Quando carrego um desses arquivos pela primeira vez, eles não mostram nenhum erro, e não mostrarão até que eu os altere e, então, todos os erros apareçam. : /

@ Angular-Angel Reparei que reiniciar o Godot resolve os erros. É decepcionante que eu não possa usar a digitação estática em Godot com classes / tipos personalizados, mas sem erros bizarros aparecendo.

"Apenas" fechar / reabrir o projeto tem sido suficiente para mim. Shift + Ctrl + Q (vá para a lista de projetos), confirme o prompt e clique duas vezes no projeto novamente. Ainda um pouco frustrante, mas você se acostuma (até consertar).

Desculpe, mas também estou um pouco frustrado, e não sabia sobre essa solução desde que vocês comentaram, parei de digitar meu código um pouco, mas ainda sinto MUITA falta.

Acordado. Este se tornou um hábito muito importante muito rápido para mim e para os outros. Provavelmente verei se a solução alternativa para reiniciar é suficiente no momento. (Godot começar rápido será ótimo) Em 16 de maio de 2019 8h27, Ricardo Alcantara [email protected] escreveu: Desculpe , mas também estou um pouco frustrado e não sabia dessa solução, pois vocês comentaram , Parei de digitar meu código por um tempo, mas ainda sinto MUITA falta.

—Você está recebendo isto porque comentou.Responda a este e-mail diretamente, visualize-o no GitHub ou ignore a conversa.

Godot 3.1.1 (não mono)
Stack.zip

exemplo reproduzível mínimo

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

_Por favor, alguém conserte isso.

image

o carregamento funciona bem, o pré-carregamento não

Observe que, na verdade, há um erro de script não detectado no StackList.gd. Especificamente, é um erro de sintaxe na declaração da chave do dicionário. No entanto, ele só é capturado quando o dicionário é alterado para uma constante.

Só queria observar que hoje também achei o bug "is" class_name.

Eu voltei a usar object.has_method ("name") em vez de testar se o objeto é className

Eu tenho acertado este aqui com frequência no 3.1.1, e me precipitando para evitá-lo.
Esperando que seja corrigido no 3.2!

Peço que não esbarre em questões sem novas informações. Todos nós sabemos que isso acontece, já temos muitos exemplos, não vou desaparecer magicamente com mais comentários.

No momento, estou tentando consertar isso em @JavaryGames , a solução já está em andamento. Não tenho certeza se ele vai entrar no 3.2, já que é uma grande mudança (tive que reconfigurar um pouco a forma como o GDScript funciona internamente) e estamos perto do lançamento, mas talvez possamos integrar no 3.2.1 ou algo assim. Definitivamente será corrigido no 4.0.

A correção em que estava trabalhando ainda é o WIP e está causando travamentos. Não estou confiante para mesclar uma mudança tão grande no estágio beta, então provavelmente será feito em uma versão 3.2.x mais tarde.

@vnen Existe algum ramo com correção para este bug, que podemos compilar e testar?

Não tenho certeza se mais informações neste ponto ajudam, mas uma solução alternativa (que funcionou para mim) é alterar o class_name da classe problemática e, em seguida, alterá-lo novamente. O que faz com que pareça estar relacionado ao cache.

Aconteceu comigo em uma linha onde eu estava lançando um membro da classe usando as logo depois de alterar a assinatura de um método da classe para a qual a variável foi lançada, mas antes de poder corrigir o método real. Então, depois de consertar o método, a linha continuou apresentando esse erro, e ele só parou quando eu finalmente mudei o nome da classe de elenco para outra coisa, e então mudei de volta.

@vnen Existe algum ramo com correção para este bug, que podemos compilar e testar?

Sim, eu tenho em meu fork público: https://github.com/vnen/godot/commits/gdscript-no-cycles

Não tenho certeza se mais informações neste ponto ajudam, mas uma solução alternativa (que funcionou para mim) é alterar o class_name da classe problemática e, em seguida, alterá-lo novamente. O que faz com que pareça estar relacionado ao cache.

Você pode obter alguns artefatos de cache no editor, pois tudo está sendo recarregado o tempo todo enquanto você edita. Mas se você encontrar esse problema, provavelmente não funcionará durante a execução, mesmo que consiga obtê-lo sem erros no editor.

https://github.com/godotengine/godot/issues/38265 parece ser um relatório duplicado com alguns detalhes de reprodução.

Quando essa correção virá na linha principal?
É super irritante porque eu uso scripts do tipo save e corro com muita frequência para esse problema.
Hoje encontro uma situação insolúvel.

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 - Erro de análise: A classe "WfcSlot" não pôde ser totalmente carregada (erro de script ou dependência cíclica).
módulos / gdscript / gdscript. cpp: 576 - Método falhou. Retornando: ERR_PARSE_ERROR

@MikeSchulze Neste caso, sinto que é em parte um problema de design: WfcSlot provavelmente não deve saber sobre WfcSlotHistory . A ação save provavelmente deve ser no último.

(Este comportamento / bug _é_ irritante, porém, não me interpretem mal.)

@ Jeto143 obrigado pela sua resposta, resolvi meu problema copiando todos os membros do Slot manualmente para o SlotHistory.
Esperançosamente, este bug será resolvido

Olá, Devs, quando esse longo ... longo bug for finalmente resolvido?

No início, preciso de vários construtores para uma classe, mas isso não é permitido, mas por quê?
Segunda tentativa, eu uso a função estática para resolver esse problema, mas também não funciona.

Eu tenho uma aula como esta (exemplo simpe)
`` ``
estende Recurso
class_name ClassA

_init (valorA: int, valorB: int):
imprime (valorA, valorB)

função estática de (valor: int) -> ClassA:
retornar ClassA.new (valor, valor)
`` ``

`` ``
var o: ClassA = ClassA.new (1,2) # está funcionando bem

var o2: ClassA = ClassA.of (2) # produz o erro

`` ``

O uso de funções estáticas produziu esse erro.
"Erro do analisador: Usar o próprio nome no arquivo de classe não é permitido (cria uma referência cíclica)"

Portanto, isso me impede de escrever uma classe para usar vários construtores onde o comportamento padrão em linguagens modernas.

Eu uso uma solução alternativa atual como esta
`` `
função estática de (valor: int) -> ClassA:
var clazz = load ("res: //../../ClassA.gd")
return clazz.new (valor, valor)
`` ``

Cumprimentos
Mike

Olá, Devs, quando esse longo ... longo bug for finalmente resolvido?

Ele será resolvido no 4.0 como parte da reescrita do GDScript.

Isso funcionará para funções estáticas também quando corrigido?

class_name Cls

static func f():
    print(Cls)

@vnen, então estamos no lançamento 3.2.X, podemos esperar uma correção em breve?

@ Ploppy3 Essas correções são devido a grandes mudanças que vêm com a reescrita do GDScript e provavelmente não é possível selecioná-las a dedo. Você terá que atualizar para 4.0 se quiser ter essas correções.

Eu também tenho esse problema, aqui estão meus dois scripts.

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

Acabei de descobrir esse problema enquanto trabalhava em meu projeto de grupo fundamental em Godot 3.2.3. Para nossos retornos de chamada de colisão, temos algo assim:

extends Area2D

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

Portanto, queremos verificar if body is Player antes de chamar métodos específicos do jogador. O problema é que Player pode ou não estar disponível, mesmo no escopo global, seja declarado via class_name ou preload -ed. Isso acontece mesmo se Player não estiver pré-carregando nosso script para causar uma dependência circular óbvia.

No momento, estamos resolvendo isso simplesmente garantindo que Player seja a única coisa na máscara de colisão de Area2D e não verificando nada no código. No início, estávamos verificando if body.name == "player" .

Fico feliz em saber que está sendo trabalhado, mesmo que demore muito, e espero que tudo corra bem.

Tive um problema de dependência semelhante quando isso me impediu de implementar um padrão Builder usando um método estático:

class_name MyClass

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

A solução alternativa descrita aqui para carregar a classe do caminho do arquivo de origem é bom, mas requer não alterar a árvore de arquivos sem alterar o código-fonte.

Eu uso este truque para ter o caminho do arquivo de origem atual, mesmo no método estático (no qual get_script () não está disponível):

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

com

class_name GodotExt

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

Este truque para obter a aula atual parece funcionar de qualquer lugar.
Ele é bruto e pode ser usado para evitar problemas semelhantes de dependência cíclica aguardando a correção da dependência global.

oi @AliBouarab bom truque

Esta página foi útil?
0 / 5 - 0 avaliações