Godot: Algunos usos de `class_name` pueden producir errores cíclicos inesperadamente

Creado en 26 ago. 2018  ·  69Comentarios  ·  Fuente: godotengine/godot

Windows 10 de 64 bits - Godot 3.1 alpha

Editar: problema refinado para centrarse en errores cíclicos.

Ciertos usos de class_name pueden producir errores cíclicos en situaciones en las que no hay referencias cíclicas y, de hecho, a veces no hay otras referencias fuera de la única dada.

He notado esto con mayor frecuencia en el script de la herramienta cuando uso is para hacer una comparación de clases, pero parece suceder a veces en situaciones normales de script.

Recrearlo en un proyecto de muestra se me ha escapado.

godot master_2018-08-27_00-47-02

bug 3.2 confirmed high priority gdscript

Comentario más útil

La solución en la que estaba trabajando sigue siendo WIP y causa bloqueos. No estoy seguro de fusionar un cambio tan grande en la etapa beta, por lo que probablemente se hará en una versión 3.2.x más adelante.

Todos 69 comentarios

Funcionará si le da al script base un class_name y lo usa en la línea de extensión.
También recibo el error al usar nombres de archivo al principio (https://github.com/godotengine/godot/blob/master/modules/gdscript/gdscript_parser.cpp#L4947), pero también desaparece y no aparece de nuevo después de que funcionó una vez (como en, después de usar la solución mencionada)

@ PetePete1984 Genial, gracias Pete. ¿Así es como se pretende utilizar entonces?

Mientras verificaba y probaba esto, estaba mirando el método get_class() y me preguntaba si debería devolver Node2D. La parte is CustomClass devuelve _true_, pero is_class("CustomClass") por otro lado es _false_.

CC @reduz @vnen @willnationsdev

No diría que es un comportamiento previsto, especialmente no con un mensaje de error que implica inclusiones cíclicas donde no las hay.
get_class() y is_class() me confunden en general, no puedo comentar sobre eso realmente. La fuente podría resolver ese misterio a largo plazo, pero hasta ahora is ha sido suficiente para mí.

@vnen ¿Sería esto algo que necesita un mensaje de error más claro?

@ PetePete1984 Sí, is ha sido algo asombroso ahora en 3.1. Aunque me encontré con una situación en la que me hubiera gustado usar el nuevo match como match custom_thing.get_class() y compararlo con varias cadenas. Pero nada crítico, solo legibilidad y menos escritura.

@avencherus Es posible que pueda salirse con la suya:

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

No estoy seguro de por qué da este error, tendré que investigar.

@willnationsdev No estoy completamente seguro de cuál es el cheque de get_script() parte, al menos para mí, devuelve un objeto GDScript [GDScript:1057] .

@vnen Gracias vnen. X) Parece que están sucediendo algunas otras cosas raras cuando volví a probar estas sugerencias para ver si podía darte una mejor información. Voy a tirar y reconstruir y jugar con él en un momento. Vea si hay algo más que agregar. Es posible que también me haya encontrado con un problema diferente en el camino.

@avencherus los "nombres de clase" de las clases de script son variables globales que hacen referencia al script. Entonces...

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

@willnationsdev Oh,

@vnen Sí, algunas arrugas adicionales a la historia. Déjame ver qué tan bien puedo articularlos.

En primer lugar, la solución de Pete funciona, cuando una clase base recibe un class_name todo parece estar bien. Lo que sí noté es que volviendo a la clase base y sacando el class_name CustomBase que agregué, funciona a medias. Ya no aparece en la lista de nodos cuando se agregan nodos, pero is funcionará y no habrá errores extraños.

Luego, para confirmar esto, fui a recrear los pasos para crear un script extendido base2.gd -> custom2.gd. Luego, dentro de custom.gd use class_name CustomClass2 , pero sin nombres de clases en la clase base.

Apareció otro problema. La lista de nodos tenía el primero, pero estaba listado con un ícono que decía "Error"

godot master_2018-08-27_20-01-26

Así que modifiqué la primera clase base para que ambos usaran class_name . Pero nuevamente obtuve resultados extraños.

No todo se muestra en la lista de nodos, y luego la palabra clave is solo devolvió verdadero para uno de ellos. Aunque en esta captura de pantalla puede ver que la lista de nodos reconoce CustomClass2, en el código detrás de ella, is CustomClass2 devuelve falso.

godot master_2018-08-27_20-05-11

Parece que muchas cosas se están cambiando o se demoran detrás de escena. Es difícil predecir lo que puede estar haciendo con mi conocimiento limitado.

Espero que ayude. X)

editar ignorar este comentario. No me había dado cuenta de que class_name no está implementado en 3.0.6, este problema se refiere a una compilación 3,1 de todos modos.

class_name parece estar roto en 3.0.6. Haré un problema por separado, pero:

image

Las clases de script

Intenté lo siguiente y cada versión funcionó. Todas las clases de secuencias de comandos aparecieron en CreateDialog, las secuencias de comandos se compilaron bien, la escena se ejecutó correctamente, etc.

Con una jerarquía de escenas como esta:

  • Nodo (base.gd)

    • Nodo (derivado.gd)

Guión:

# 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 ejecuté la prueba, imprimió

base
derived
base

...como debería.

Mi sugerencia sería intentar borrar el caché de archivos de su editor (si tal vez hubo cambios en la forma en que se almacenó el caché de archivos en medio de su programación / actualización del motor, eso de alguna manera podría estropear las cosas hasta que lo borre).

@willnationsdev Gracias por mirar, probaré esto. ¿Son estos los archivos de la carpeta AppData / Roaming? Seguiré adelante y aclararé todo por ahora. Si es así, ¿me pregunto si hay algo más específico que debería eliminar?

@avencherus No estoy muy seguro. Solo recuerdo que @karroffel mencionó algo al respecto cuando agregué algunas correcciones al ícono de la clase de script anteriormente.

Probado en https://github.com/godotengine/godot/commit/1093c0ff51b980634dffdd9618eaa53061da6419
No veo ningún error, pero no muestra el nodo en el cuadro de diálogo "Crear nuevo nodo".

También recibo el error que se muestra en la publicación original (Windows x64 Godot 3.1 alpha):

image

Sin embargo, sucede en un contexto diferente. Tengo 3 scripts que cada uno tiene un class_name , y cada uno de ellos extiende Node2D. El error no ocurre a menos que uno de los scripts lo haga referencia con el operador is . Por ejemplo if some_var is Incomer . Sin embargo, lo extraño es que si el mismo script hace referencia al otro class_name, no hay problema. Y si el otro script hace referencia al class_name en cuestión, tampoco hay problema.

Entonces hay una ClassA, ClassB, ClassC. Si ClassC hace referencia a ClassA con el operador is , entonces error en el tiempo de carga. Si ClassC hace referencia a ClassB, no hay error. Si ClassB hace referencia a ClassA, no hay error.

Ninguno de los guiones está en la misma escena y todos los nodos son hermanos (sin relación de antepasados).

@AlexHolly La misma situación conmigo ahora también. El error parece haber desaparecido, pero sí, las clases no aparecerán en la ventana de agregar nodo cuando no se tenga un script base que también use class_name .

Esto está en alpha 3.1 c320d93

Un pequeño ejemplo usando "es". Lo mismo puede suceder si usa "como".
Esto también fue mencionado por @Oranjoose .
ciclo.zip

Ninguno de los guiones está en la misma escena y todos los nodos son hermanos (sin relación de antepasados).

Esto no tiene nada que ver con los nodos de la escena. Los ciclos ocurren en el propio guión.

Por ahora, es bastante fácil obtener ciclos al usar is y as y si sucede, no es realmente un error, es la forma en que es. Intentaré mejorar esto, pero no para 3.1. El informe original es un error porque no hay ciclos reales en el código.

No pude reproducir el error en 451e5fd también. Aunque el nodo no apareció en la ventana de creación.

Puedo confirmar que este problema no está presente en 0dbe014 (el último maestro que extraje). Probablemente podamos cerrar este problema.

Además, pude hacerlo para que las clases de script que extienden los scripts todavía aparezcan en CreateDialog, lo cual todavía era un error. PR está vinculado arriba.

@willnationsdev Gracias Will. X) Me he encontrado con varios problemas con class_name , pero no he podido recrear este. Han sido terriblemente difíciles de recrear, pero desde entonces dejé de usarlos.

He notado que a veces pueden aparecer errores vagos y no relacionados en un script debido a errores en un script al que se hace referencia. Se vuelven más significativos al abrir el guión culpable, y cuando se arreglan, estos otros también se borran.

Sin embargo, volveré a adaptar el tema de la publicación, porque este error cíclico parece seguir ocurriendo en situaciones extrañas y es difícil de alcanzar al intentar recrearlo. Así que probablemente todavía hay algo, lo dejaré abierto para vnen.

@avencherus ya veo. Bueno, espero que eventualmente puedas identificar bajo qué condiciones está sucediendo. Sin el contexto, no podemos arreglarlo. XD

He notado algunos errores de referencia cíclicos que ocurrieron en mi trabajo de godot-next donde pude usar la escritura estática para decir que estaba devolviendo el mismo tipo que el nombre de clase del script, pero si intenté hacer referencia al nombre de la clase del script (para crear una instancia para regresar más tarde en la función), no funcionaría porque el script haría referencia a sí mismo y, por lo tanto, necesitaría cargarse de forma recursiva infinitamente.

La solución que encontré fue usar load(get_script().resource_path).new() . Todo un bocado, lo sé, pero le permitió al analizador construir los datos de forma segura y pasar el proceso de compilación de forma segura, dejar que el nombre del tipo se registrara oficialmente y luego solo hacer referencia al tipo en RUNTIME una vez que se había inicializado por completo.

Periódicamente seguiré haciendo un esfuerzo por desentrañarlo. Ojalá pudiera ser de más ayuda, pero me imagino que tendrán que esperar hasta que aquellos con un conocimiento profundo de su implementación estén trabajando en sus propios proyectos y se encuentren de frente con estos problemas. Apostaría a que sabrían dónde poner su mirada en esa situación.

Un resumen rápido de algunos de los problemas (los publicaré en las próximas semanas):

  1. Obtendría estos errores cíclicos al hacer obj is MyClass y no había otra conexión o referencia entre los dos. Aunque no sé si está escaneando el árbol de la escena y contando sus hijos como referencias cíclicas.
  2. También me he encontrado con los inconvenientes que ha descrito. Ojalá no fuera así, porque funciona bien con nombres de clases nativos / integrados en los mismos tipos de situaciones. Entonces, puede escribir un montón de código con este objetivo final en mente pensando que todo está bien, hasta que comience a agregar sus tipos personalizados, y tenga que recurrir a un método de pirateo / solución alternativa / más antiguo, y luego lo que fue el valor de la misma si no es para evitar nombres de ruta detallados?
  3. He tenido estas cosas sin errores en el editor y ejecutándome de forma limpia durante las pruebas, pero luego tengo errores y fallas en el juego exportado. Un ejemplo a continuación (aunque probablemente no esté relacionado con este problema) es que el uso de class_name no pudo encontrar sus iconos en la compilación, pero no hubo problemas en las ejecuciones y pruebas del editor.

gtc_2018-10-12_13-21-35

En general, mis experiencias con class_name han sido un encuentro casi diario con muchos errores impredecibles, difíciles de explicar y difíciles de reproducir. Se pierde mucho tiempo bailando alrededor y tratando de resolverlos.

Tenía muchas ganas de verlos, y absolutamente harían que la codificación de ciertas cosas fuera mucho más compacta y legible. Por razones prácticas de tiempo, tengo que dejarlos de lado y optar por no usarlos en mi proyecto actual.

Quizás en 4.0. X)

Voy a volver al antiguo método de rutas de script. Al hacerlo, sería mi preferencia usarlos hasta el final para evitar sorpresas class_name azar y para mantener el código más consistente.

Como dije antes, es muy fácil crear ciclos con class_name , especialmente cuando se usa is y as . Es menos fácil con las rutas, pero también puede encontrarse con problemas similares. El problema es que GDScript nunca se conectó para funcionar así, por lo que depende demasiado de la carga de recursos. Tengo algunas ideas para solucionar esto (en particular, simplemente ignorando la carga de recursos y haciendo análisis superficial de dependencias directamente), pero esto requiere un cambio estructural del analizador.

Probablemente se resuelva correctamente en las próximas versiones, ya que no es un buen momento para meterse con esto. class_name será una "característica menor" por ahora. Aún puede usarlo en algunos casos, pero no tan extensamente como espera.

@vnen Hola. Dar una buena acogida. X)

Gracias por la respuesta y el cronograma.

Sí, es por eso que tengo que guardarlo por ahora. Fui un poco lento para darme cuenta de que no era una integración tan fluida, adecuada o natural. (Estaba recibiendo indicios de esto cuando vi todas las entradas en el archivo del proyecto).

Supongo que parece una característica "menor", pero tendrá algunos beneficios muy serios si se pueden solucionar las arrugas. Realmente lo espero con ansias, y siento su pérdida después de usarlo ya. Definitivamente es un buen camino a seguir para GDScript.

Una cosa importante que me faltará es la capacidad de recurrir a sugerencias cuando una clase personalizada se combina con su nueva sugerencia de tipo. var thing : NewThing

Cuando hago una clase grande durante unos días, y tal vez unos días después, aparece la primera vez que se usa, encuentro que no recuerdo al 100% los nombres con precisión de cada función hasta que los he usado varias veces. Entonces, recibir estos consejos fue un aumento de productividad bastante inesperado y significativo para mí. Pude quedarme y trabajar en un área por mucho más tiempo.

Ciertamente, el núcleo del problema es, como usted dice, los ciclos fáciles, pero creo que mis peores experiencias han sido que actualmente algunos de los errores no apuntan a los lugares correctos. Han pasado algunas semanas, pero he tenido situaciones en las que usé una clase personalizada y todo estuvo bien durante unos días. Luego escribí más código que llamaba a esa clase personalizada, y en algún momento durante el desarrollo comencé a recibir errores de ciclo. En algunos casos, estos errores no ayudaron a explicar dónde estaba ocurriendo el error. Para encontrarlo, tuve que buscar y eliminar todos los usos de nombres de clase uno por uno hasta que se detuvo el error.

Solo unos pocos incidentes como ese han recuperado gran parte de las ganancias. Me da miedo imaginar que se produzca un problema como ese en algún lugar de 30.000 líneas.

El único incidente que me hizo tirar de todos ellos fue aquel en el que los errores de ciclo solo aparecían en la compilación de exportación y arrojaban errores de script no relacionados. Creo que uno decía que las texturas de los iconos no se encontraron, pero en realidad no fue así, y se aclaró cuando abandoné algunos usos de class_name. Sospecho que class_name estaba fallando y el error se encontraba en la siguiente línea.

Lo he visto suceder a veces cuando ocurren errores en la línea por encima o por debajo de la causa.

Es realmente difícil para mí y para mi conocimiento cero aquí identificar el origen de muchos de estos problemas. Mucho de esto está simplemente detrás de la cortina para mí, y estoy agradecido de que pueda descifrar algo de esto.

En 3.1 ha habido muchos eventos inusuales con las advertencias y errores, así que me pregunto si el problema es la cosa en sí o un problema con la lógica de informe de errores. Todavía no sé exactamente por dónde empezar, y solo puedo esperar que algo de esto termine siendo útil, y también, con el tiempo, poder reducirlos a pequeños proyectos.

EDITAR: No importa, de alguna manera simplemente resolví la inclusión cíclica simplemente por no hacerlo ...
Las clases globales en project.godot se sobrescriben de todos modos al iniciar el editor.

@vnen o @avencherus Sería bueno actualizar el OP con una descripción clara de de qué se trata este error al final, ya que de lo contrario es una discusión larga para leer antes de tener una buena idea.

@ akien-mga Ya no estoy muy seguro de su estado, o de qué escribir específicamente sobre él.

Si mal no recuerdo, hay al menos algunas partes. Los errores cíclicos esperados como una limitación de GDScript en su forma actual, y luego aparecen los inesperados que son difíciles de aislar y reproducir en proyectos pequeños (a veces debido a mensajes de error inexactos).

Dado que no es una función que esté usando actualmente, no he seguido el progreso. Creo que algunas cosas aquí y allá se han arreglado desde entonces.

De un vistazo a estos otros temas, parece que la charla trata sobre los cambios necesarios en GDScript. Con las revisiones dirigidas a 3.2. Si ese es el plan, entonces ya no estaría por debajo del hito 3.1.

Probablemente esté bien cerrar esto, a menos que vnen lo esté usando para la contabilidad, o si prefiere usarlo para consultar los próximos problemas duplicados cuando 3.1.0 aterrice estable.

La función es una ventaja de usabilidad que me interesa, por lo que es muy probable que la revise en 3.2 y publique cualquier hallazgo.

Bueno, esto no debería cerrarse, no, la gran cantidad de informes duplicados definitivamente muestra que hay algo que arreglar :)

Me encontré con el siguiente mensaje de error que me resulta problemático al actualizar un proyecto de 3.0 a 3.1. Anteriormente, el siguiente código funcionaba:

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

Cuando cambio el código a:

extends Node2D
class_name SomeClass

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

Obtuve el siguiente error:

Error de análisis: no se permite usar un nombre en el archivo de clase (crea una referencia cíclica)

Esto es frustrante para mí ya que todos los nodos secundarios que estoy buscando heredan de esta clase y se mezclan con otros nodos secundarios que no lo hacen. ¿Es la capacidad de escribir verificación para otras instancias de una clase de script que no funciona de esta manera y hay otra forma en que debería hacerlo?

@Diaspater Creo que todo lo que tienes que hacer es cambiar if c is SomeClass a if c is get_script() . Ambas opciones ejecutan una verificación en tiempo de ejecución, pero la versión SomeClass requiere que cargue el script nuevamente en el tiempo del editor (lo que resulta en una referencia cíclica) mientras que el método get_script() no intenta hacer nada en tiempo de redacción.

@willnationsdev Entiendo que es una solución válida (o una solución alternativa a mi problema, como me di cuenta después de escribir mi comentario original de que la primera forma todavía funciona. Dicho esto, preferiría que la segunda forma pudiera ser compatible correctamente. También descubrí que esto 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

Dicho esto, entiendo su explicación de por qué actualmente da un error. Con múltiples soluciones o soluciones alternativas a este problema, creo que este no es un error esencial para corregir, pero sigue siendo un error que me gustaría ver corregido en algún momento en el futuro.

Después de usar este método en usos un poco más complejos, parece que esto está causando otros errores cíclicos en otras ubicaciones en otros scripts acoplados, por lo que probablemente esta no sea una buena solución / solución alternativa al problema.

Esta puede ser una pregunta ingenua, pero ¿no deberíamos deshacernos de esta restricción no cíclica?
Me refiero a otros lenguajes como Java, C #, C ++, etc ... pueden manejar tipos sin problemas ...

@harraps que se hará (como dije varias veces en el hilo), pero requiere algunos cambios fundamentales en cómo se conecta GDScript. No tocaré esto ahora ya que estamos cerca de su lanzamiento y este cambio probablemente romperá la compatibilidad.

En caso de que otros encuentren esto, he encontrado otra instancia de un error relacionado con una "referencia cíclica", pero es diferente de los demás enumerados aquí.

Si crea una clase con un método de fábrica estático que hace referencia al nombre de la clase actual en el valor de retorno, no informará ningún tipo de error dentro del propio editor, pero una vez que el editor se cierre, obtendrá un informe de error. que los recursos todavía se están utilizando.

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

Entonces obtienes este error:

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

Volviendo a publicar desde # 944,

También me encuentro con dependencias cíclicas de GDscript con regularidad. Aquí hay algunos casos de uso en los que actualmente me veo obligado a volver a GDscript sin tipo:

  1. Mis personajes usan un ActorController que ejecutan diferentes Move s (como estados en una máquina de estado). El ActorController reenvía _physics_process() y así al activo Move . Viceversa, el movimiento accede a ActorController para cambiar a otro Move o acceder a propiedades (como altura de salto, velocidad de carrera, etc.)

  2. La misma situación con mi MoveRepository : el repositorio almacena Move s reutilizables, pero los Move s también necesitan acceder al repositorio si quieren obtener otro Move para seleccionarlo en su ActorController

actor-framework

Esto no es un problema en C # o C ++, pero GDscript (con tipado estático opcional) requiere que recurra a variantes (tipado dinámico) o cree indirecciones innecesarias usando eventos y demás.

También tengo este problema. Tengo una configuración similar pero más simple.
La clase TurnManager tiene una variable de tipo Actor y cada Actor tiene una referencia escrita al TurnManager
Ni siquiera estoy usando is Literalmente acabo de declarar las variables y es suficiente para provocar este error.
Usando la nueva versión estable 3.1 en Linux de 64 bits.

image

Me encontré con esto. Parece relacionado.

image

Muy extraño en verdad.

image

Yo también parece que me estoy encontrando con esto. Me preguntaba si es porque tenía los scripts en su mayoría separados de los objetos. Tengo una clase de atributo base, que extiende el nodo, y PrimaryAttribute y SecondaryAttribute extendiéndolo, y luego como 12 nodos PrimaryAttribute y un nodo SecondaryAttribute. Sin embargo, al editor no parece gustarle. Aunque el juego funciona bien cuando lo juego.

Es de destacar que cambié las rutas de recursos para class_names, y eso hizo que las cosas funcionaran bien durante aproximadamente 5 minutos antes de que volvieran a darme errores sin ningún motivo. : /

Hmm. ¿Los errores parecen tener que ver con el orden en que se cargan las cosas en la ventana del editor? Puedo hacer que desaparezcan cerrando y volviendo a abrir archivos en el orden en que los heredaron. Entonces, probablemente algún tipo de problema al no declarar cosas en algunos archivos. : /

Editar: En realidad, no, no importa en qué orden abra los archivos, o incluso si tengo otros archivos abiertos. Cuando cargo uno de estos archivos por primera vez, no muestran ningún error y no lo harán hasta que los cambie y luego aparezcan todos los errores. : /

@ Angular-Angel He notado que reiniciar Godot resuelve los errores. Es decepcionante que no pueda usar la escritura estática en Godot con clases / tipos personalizados sin que aparezcan errores extraños.

"Solo" cerrar / reabrir el proyecto ha sido suficiente para mí. Shift + Ctrl + Q (ir a la lista de proyectos), confirmar el mensaje y luego hacer doble clic en el proyecto nuevamente. Sigue siendo un poco frustrante, pero te acostumbras (hasta que se soluciona).

Lo siento, pero yo también estoy un poco frustrado, y no sabía acerca de esa solución desde que ustedes comentaron, dejé de escribir mi código por un tiempo, pero todavía lo extraño MUCHO.

Convenido. Esto se convirtió rápidamente en un hábito clave para mí y para los demás. Probablemente veremos si la solución de reinicio es suficiente por el momento. (Godot comenzar rápido será genial) El 16 de mayo de 2019 8:27 a.m., Ricardo Alcantara [email protected] escribió: Lo siento , pero yo también estoy un poco frustrado, y no sabía acerca de esa solución desde que ustedes comentaron , Dejé de escribir mi código un rato, pero todavía lo extraño MUCHO.

—Está recibiendo esto porque comentó. Responda a este correo electrónico directamente, véalo en GitHub o silencia el hilo.

Godot 3.1.1 (no mono)
Stack.zip

ejemplo mínimo reproducible

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

_por favor_ alguien arregle esto.

image

La carga funciona bien, la precarga no

Tenga en cuenta que, de hecho, hay un error de secuencia de comandos no detectado en StackList.gd. Específicamente, es un error de sintaxis en la declaración de la clave del diccionario. Sin embargo, solo se detecta una vez que el diccionario se cambia a una constante.

Solo quería tomar nota de que hoy también encontré el error "es" class_name.

He vuelto a usar object.has_method ("nombre") en lugar de probar si el objeto es className

He estado golpeando este a menudo en 3.1.1 y saltando a través de aros para evitarlo.
¡Esperando que se solucione en 3.2!

Les pido por favor que no surjan problemas sin nueva información. Todos sabemos que esto sucede, ya tenemos muchos ejemplos, no desaparecerá mágicamente con más comentarios.

Actualmente estoy tratando de solucionar este problema en @JavaryGames , la solución ya está en marcha. No estoy seguro de si se convertirá en 3.2 ya que es un gran cambio (tuve que volver a cablear un poco cómo funciona GDScript internamente) y estamos cerca de su lanzamiento, pero tal vez podamos integrarlo en 3.2.1 o algo así. Definitivamente se arreglará en 4.0.

La solución en la que estaba trabajando sigue siendo WIP y causa bloqueos. No estoy seguro de fusionar un cambio tan grande en la etapa beta, por lo que probablemente se hará en una versión 3.2.x más adelante.

@vnen ¿Hay una rama con solución para este error que podamos compilar y probar?

No estoy seguro de si más información en este punto ayuda, pero una solución alternativa (que funcionó para mí) es cambiar el class_name de la clase problemática y luego volver a cambiarlo. Lo que hace que parezca estar relacionado con la caché.

Me sucedió en una línea en la que estaba lanzando un miembro de la clase usando as justo después de cambiar la firma de un método de la clase a la que se envió la variable, pero antes de que pudiera arreglar el método real. Luego, después de corregir el método, la línea seguía dando este error, y solo se detuvo cuando finalmente cambié el nombre de la clase de conversión a otra cosa, y luego lo volví a cambiar.

@vnen ¿Hay una rama con solución para este error que podamos compilar y probar?

Sí, lo tengo en mi bifurcación pública: https://github.com/vnen/godot/commits/gdscript-no-cycles

No estoy seguro de si más información en este punto ayuda, pero una solución alternativa (que funcionó para mí) es cambiar el class_name de la clase problemática y luego volver a cambiarlo. Lo que hace que parezca estar relacionado con la caché.

Es posible que obtenga algunos artefactos de almacenamiento en caché en el editor, ya que todo se recarga todo el tiempo mientras edita. Pero si llega a este problema, lo más probable es que no funcione cuando se ejecuta, incluso si logra obtenerlo sin errores en el editor.

https://github.com/godotengine/godot/issues/38265 parece ser un informe duplicado de esto con algunos detalles de reproducción.

¿Cuándo llegará esta solución a la línea principal?
Es muy molesto porque uso scripts de tipo save y me encuentro con este problema muy a menudo.
Hoy me encuentro con una situación insoluble.

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 - Error de análisis: la clase "WfcSlot" no se pudo cargar por completo (error de script o dependencia cíclica).
módulos / gdscript / gdscript. cpp: 576 - El método falló. Regresando: ERR_PARSE_ERROR

@MikeSchulze En este caso, siento que es en parte un problema de diseño: WfcSlot probablemente no debería saber sobre WfcSlotHistory . La acción save probablemente debería estar en este último.

(Este comportamiento / error _es_ molesto, no me malinterpretes).

@ Jeto143 gracias por su respuesta, resolví mi problema copiando todos los miembros de Slot manualmente en SlotHistory.
Ojalá se solucione este error

Hola, desarrolladores, ¿cuándo se resolverá finalmente este largo ... largo error?

Al principio, necesito varios constructores para una clase, pero esto no está permitido, pero ¿por qué?
Segundo intento, uso la función estática para resolver este problema, pero esto tampoco funciona.

Tengo una clase como esta (ejemplo de simpe)
`` ``
extiende el recurso
class_name ClassA

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

función estática de (valor: int) -> ClassA:
return ClassA.new (valor, valor)
`` ``

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

var o2: ClassA = ClassA.of (2) # produce el error

`` ``

El uso de la función estática produce este error.
"Error del analizador: no se permite usar un nombre propio en el archivo de clase (crea una referencia cíclica)"

Entonces, esto me bloquea para escribir una clase para usar múltiples constructores donde sea un comportamiento estándar en los lenguajes modernos.

Utilizo una solución hacky actual como esta
''
función estática de (valor: int) -> ClassA:
var clazz = load ("res: //../../ClassA.gd")
return clazz.new (valor, valor)
`` ``

Atentamente
Miguel

Hola, desarrolladores, ¿cuándo se resolverá finalmente este largo ... largo error?

Se resolverá en 4.0 como parte de la reescritura de GDScript.

¿Funcionará esto también para funciones estáticas cuando se arregle?

class_name Cls

static func f():
    print(Cls)

@vnen, así que estamos en la versión 3.2.X, ¿podemos esperar una solución pronto?

@ Ploppy3 Estas correcciones se deben a cambios masivos que vienen con la reescritura de GDScript y es probable que no sea posible seleccionarlas. Tendrá que actualizar a 4.0 si desea tener estas correcciones.

También tengo este problema, aquí están mis dos 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

Acabo de descubrir este problema mientras trabajaba en mi proyecto de grupo final en Godot 3.2.3. Para nuestras devoluciones de llamada de colisión, tenemos algo como esto:

extends Area2D

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

Así que queremos comprobar if body is Player antes de llamar a métodos específicos del jugador. El problema es que Player puede o no estar disponible, incluso si está en el ámbito global, ya sea que se declare a través de class_name o preload -ed. Esto sucede incluso si Player no está precargando nuestro script para causar una dependencia circular obvia.

Actualmente estamos trabajando alrededor de esto simplemente asegurándonos de que Player sea ​​lo único en la máscara de colisión de Area2D y sin verificar nada en el código. Al principio estábamos comprobando if body.name == "player" .

Me alegra saber que se está trabajando en ello, aunque esté tardando mucho, y espero que todo vaya bien.

Tuve un problema de dependencia similar cuando eso me impidió implementar un patrón Builder usando un método estático:

class_name MyClass

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

La solución que se describe aquí para cargar la clase desde la ruta del archivo fuente es buena, pero requiere no cambiar el árbol de archivos sin cambiar el código fuente.

Utilizo este truco para tener la ruta del archivo fuente actual incluso en el método estático (en el que get_script () no está disponible):

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

con

class_name GodotExt

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

Este truco para obtener la clase actual parece funcionar desde cualquier lugar.
Está en bruto y se puede utilizar para evitar un problema de dependencia cíclica similar a la espera de la reparación de la dependencia global.

hola @AliBouarab buen truco

¿Fue útil esta página
0 / 5 - 0 calificaciones