Godot: Nadie sabe cómo funciona Godot. (Nodo basado en Re-MultiScript, Re-Class)

Creado en 16 oct. 2018  ·  63Comentarios  ·  Fuente: godotengine/godot

Este es más un tema informal, pero es un problema drástico, si no el principal problema de Godot.
Nadie sabe cómo los desarrolladores del motor Godot planearon que los usuarios lo usaran.

Algunos problemas relacionados: #19486 #7402 #15996 #8502
Estos son los 4 principales, pero hay muchos similares que tienen como objetivo resolver el mismo problema: todos buscan un flujo de trabajo utilizable.

Sorprendentemente, los usuarios de Godot han logrado crear flujos de trabajo ineficientes que copian otros motores familiares. Para demostrar esto, usaré una clase simulada de cómo se vería una MeshInstance , si se hiciera en Godot.


Hay pseudo Unity, también conocido como nodos secundarios:


Los usuarios de Godot usan nodos secundarios para crear un equivalente a MultiScripts.

MeshInstance(Spatail +script)
--- Malla(Malla +script)
--- Material (nodo +script) - Shader (nodo +script) - Textura (nodo +script)
--- Transformar (Posición3D +script)

Básicamente, usarán el nodo más apropiado y codificarán lo que necesitan para crear la clase que quieren usando un script.

Problemas:
1.) Es el equivalente digital de agregar agua fría a una olla hirviendo; ayuda a corto plazo pero causa más confusión en proyectos más grandes.
2.) La mayoría de los usuarios terminan usando señales como eventos, conectándolas solo al nodo que las envía y usando Exportar para encontrar el objetivo.
3.) Los eventos se pueden interceptar antes de llegar a los nodos inferiores.
4.) El rendimiento es lento y alrededor de 50 000 objetos puede detenerse cuando el juego intenta cargar escenas.


Pseudo Unreal, también conocido como controladores e intermedios:

Los usuarios de Godot crean controladores y nodos poseedores que manipulan a todos los niños. La marca registrada de este flujo de trabajo son las clases derivadas con extensiones.

MeshWithTexturedMaterial.instanced() *solo nodo en el árbol
-> se extiende desde -> MaterialTexturizado -> se extiende desde -> Material -> se extiende desde -> Shader

Este sistema requiere una gran planificación, o terminará con un código similar en muchas clases. Como una cámara, clases de personajes y vehículos que contienen su propia copia de "seguir objetivo"
Problemas:
1.) Grandes secuencias de comandos desordenadas que son difíciles de depurar.
2.) Código duplicado en diferentes clases.
3.) Godot no trata los nodos como clases; obligando a estos desarrolladores a depender en gran medida de las clases autocodificadas.
4.) Las extensiones no tienen sentido, como un _sistema de combate_ extendiendo un _sistema de armas_ y finalmente extendiendo al jugador.


Pseudo Panda3D, también conocido como Preload (Script):

Éste replica el flujo de trabajo de cómo funcionan la mayoría de los motores basados ​​en código. Los desarrolladores a menudo tendrán más scripts que nodos.

Instancia de malla (nodo)
Precarga (script de malla)
Precarga (Script de materiales)
Precargar (Transformar secuencia de comandos)

Curiosamente, son estos desarrolladores los que se niegan a abandonar GDscript, incluso cuando C# es claramente mejor para este enfoque. Es por eso que asumo que están familiarizados con Python.
Problemas:
1.) Confusión sobre cómo se deben llamar las importaciones, ya que las constantes pueden ser variables con onready; quién sabe.
2.) Rara vez usa los nodos de Godot, incluso he visto a los desarrolladores ignorar las herramientas de la interfaz de usuario por completo.
3.) Dolor para depurar ya que no hay indicación de dónde está vinculado un script.


Guión WTF:

Dejó lo mejor para el final. Algunos desarrolladores de juegos de Godot han logrado hacer buenos juegos usando Señales y Grupos.

MeshInstance (Nodo) que tiene un nodo vacío en la parte superior permite un fácil movimiento y rediseño de los elementos secundarios.
--- Malla (Malla +Script || Señal)
--- Material (Sprite +Script || Señal)
--- Transformar (Posición3D +Script || Señal)

Cuando el árbol tiene que conectar objetos de 2 escenas o más de profundidad, se usará un grupo en su lugar. Lo notable de este flujo de trabajo es cómo tiene árboles poco profundos.
Problemas:
1.) Las señales y los grupos permiten que partes completas del juego fallen, sin siquiera una advertencia.
2.) Pequeños guiones sin sentido simplemente merodeando. Todo lo que hacen es enviar una señal y rastrear un solo valor.
3.) Mover un objeto con tantas señales adjuntas es frustrante en lo más mínimo.
4.) Conflictos con el sistema de instancias. Porque las instancias fluyen hacia abajo mientras que la señal se conecta mejor hacia arriba.

Sí, sé que Godot tiene una clase MeshInstance .
El punto que esto demuestra es que la mayoría de los flujos de trabajo utilizados por los desarrolladores en este momento pueden hacer una clase tan compleja como MeshInstance con múltiples componentes; excepto que cada flujo de trabajo tiene fallas graves.

Todos estos flujos de trabajo comparten el mismo problema central. Son soluciones a corto plazo para desarrollar un juego.
Ninguno de ellos escala bien y la depuración es defectuosa en todos ellos.

Lo que los desarrolladores de juegos de Godot necesitan de los desarrolladores de Engine es una clara desaceleración de lo que es el flujo de trabajo oficial para crear objetos y sistemas complejos.
De esa manera se desvían, pero siempre saben cómo se pretendía utilizar.

archived discussion core

Comentario más útil

Si la pregunta es simplemente: "¿Hay varias formas de lograr el mismo resultado en Godot?", la respuesta es sí. Y tratar de forzar un solo flujo de trabajo es absurdo, ya que cada sistema en un juego puede tener diferentes requisitos. No codificas de la misma manera un sistema que requiere muchas actuaciones y uno que requiere que un diseñador de juegos lo actualice con frecuencia. Todas las soluciones tienen compensaciones, por lo que no tiene sentido crear un flujo de trabajo "oficial".

Todos 63 comentarios

Si la pregunta es simplemente: "¿Hay varias formas de lograr el mismo resultado en Godot?", la respuesta es sí. Y tratar de forzar un solo flujo de trabajo es absurdo, ya que cada sistema en un juego puede tener diferentes requisitos. No codificas de la misma manera un sistema que requiere muchas actuaciones y uno que requiere que un diseñador de juegos lo actualice con frecuencia. Todas las soluciones tienen compensaciones, por lo que no tiene sentido crear un flujo de trabajo "oficial".

puede hacer una clase tan compleja como MeshInstance con múltiples componentes

¿Con qué componentes exactamente?

EDITAR: Y para que lo sepas, uno de los problemas que citaste se cerró con el autor diciendo: "Esta idea realmente apesta y es completamente absurda".

Para demostrar esto, usaré una clase simulada de cómo se vería una MeshInstance, si se hiciera en Godot.
Hay pseudo Unity, también conocido como nodos secundarios:
Los usuarios de Godot usan nodos secundarios para crear un equivalente a MultiScripts.
Pseudo Unreal, también conocido como controladores e intermedios:
Pseudo Panda3D, también conocido como Preload (Script):
Guión WTF:
Sí, sé que Godot tiene una clase MeshInstance.
El punto que esto demuestra es que la mayoría de los flujos de trabajo utilizados por los desarrolladores en este momento pueden hacer una clase tan compleja como MeshInstance con múltiples componentes; excepto que cada flujo de trabajo tiene fallas graves.

No entiendo muy bien lo que estás tratando de decir aquí. ¿Por qué alguien crearía una clase MeshInstance si ya existe una? ¿Y por qué es un problema que Godot tenga características similares a otros motores? Además, si está tratando de adjuntar varios scripts a un nodo, no usa OOP o está poniendo dos funcionalidades separadas en un nodo, lo que se soluciona fácilmente usando el sistema de nodos de Godot.

Si la pregunta es simplemente: "¿Hay varias formas de lograr el mismo resultado en Godot?", la respuesta es sí...

Si hago un martillo, sé para qué sirve, sé para qué no debe usarse, incluso si no sé todo para qué podría usarse.
Si le das un martillo a una persona que no tiene idea de lo que es, y nunca le explicaste cómo usarlo; no puedes actuar sorprendido cuando comienzan a balancearse salvajemente.

Aquí es donde está Godot, los desarrolladores se balancean en la oscuridad, con la esperanza de que de alguna manera esto les permita crear algo.

¿Con qué componentes exactamente?

Cosas como materiales y transformaciones, ¿se consideran parte de la instancia original o no?
Si creamos componentes similares, ¿cómo los adjuntamos al nodo?

¿Qué pasa con otras tareas, como "seguir el objetivo" o "disparar al objetivo", si se agregan a la clase o se adjuntan de alguna manera?
Dado que Godot nunca hizo funciones adecuadas de inclusión o importación para Godot, ¿eso significa que nunca fue destinado a ser usado de esa manera?

Sabemos que no podemos tenerlo todo, entonces la pregunta es ¿qué tenemos? ¿Cómo fue el diseño para trabajar?

@MysteryGM Las analogías sueltas y desconectadas no son útiles.

Cosas como materiales y transformaciones.

Transformar es una propiedad espacial y los materiales son una propiedad de malla. MeshInstance se basa en Spatial, por lo que hereda todas las propiedades de Spatial. Es una jerarquía simple que tiene sentido para mí.

Si creamos componentes similares, ¿cómo los adjuntamos al nodo?

¿Por qué crearías tu propio sistema Mesh cuando Godot ya los tiene?

¿Qué pasa con otras tareas, como "seguir el objetivo" o "disparar al objetivo"?

El código va en scripts. Puedes ponerlo en el script principal del nodo o darle un child con un script si crees que sería más útil hacerlo de esa manera.

¿Por qué crearías tu propio sistema Mesh cuando Godot ya los tiene?

Porque los objetos del juego son tan complejos como una malla, si se nota más. Recuerda que los motores eran parte de los juegos originales, solo era la parte reutilizada.

Si Godot no puede crear una clase de malla dentro del motor de manera efectiva, entonces no se puede usar para hacer juegos complejos. Todos los juegos tendrán que ser menos complejos que el motor.
Esto a su vez significa que no es de utilidad para un equipo profesional de desarrolladores. A menos que dicho equipo solo use C++ con el código fuente.

El código va en scripts.

¿Pero de qué manera?
Ya sé que no puedo hacer un niño para cada script porque necesitaré más de un millón de funciones e incluso un millón de nodos vacíos es demasiado para Godot.
¿Qué significa eso, cuántas funciones deben agruparse o debo pasar de 2 a 4 meses planificando la herencia de mi objeto en papel?

Lo que quiero saber es ¿cómo lidia Godot con juegos grandes con sistemas complejos como efectos climáticos, niebla volumétrica y terrenos grandes?

Lo siguiente se relaciona conmigo, mis opiniones y experiencia, _YMMV_

Cada motor tiene sus peculiaridades, y Godot no es diferente. Si soy honesto, dado el tiempo que ha pasado desde su primer lanzamiento estable, definitivamente estoy atónito por lo bueno que es y lo rápido que evolucionó. Esa puede ser la razón de algunos de los problemas que tenemos. El sistema de escena/nodo es mi parte favorita, la simplicidad de los nodos con guión es realmente lo que brilla para mí. A pesar de que tiene sus inconvenientes para mí, no me gustan las sintaxis similares a las de Python... y el sistema de precarga... no podía encontrar la manera de hacer que C# funcionara.

Tomando Unity 4/5 como ejemplo (al que estuve encadenado durante años), tiene _componentes_ tan inflados que no se puede comparar con ningún otro ECS que haya usado. Y, oh, ¿quieres hacer una solicitud http? Claro, agregue un nuevo componente a un nuevo objeto a su estructura de escena porque tiene mucho sentido acoplar solicitudes http con objetos en escena y sus componentes. La función "guardar una escena sin cambios rompe todos los UUID" parecía haber sido acuñada solo para dificultar el uso del control de versiones a nuestros diseñadores no expertos en tecnología. Ni siquiera quiero comenzar con "Don't Destroy On Load" y prefabricados.

¿Cuál era la lógica entre la mayoría de esas cosas de todos modos? Diría que es probablemente un desarrollo orgánico e iterativo, y algunas soluciones alternativas aquí y allá (que también se encuentran en Godot y probablemente en todos los demás motores de juegos). Es decir, se estrelló tanto que mi teclado Swift comenzó a predecir las palabras "_Unity falla_" cada vez que escribía "_Con_". Esa fue una parte importante de mi flujo de trabajo, bloquee -> vuelva a importar todos los activos por un minuto, trabaje durante 30 ', repita.

He visto tanto uso blasfemo de monocomportamiento, pero ¿a quién puedo culpar? El motor permite a las personas poner un _GameState_ "_component_" dentro de un objeto de luz puntual. ¿Deberíamos prohibirlo? ¿Cómo argumento que los datos del estado del juego ni siquiera deberían estar dentro del componente de un objeto de escena cuando la comunicación http (o prácticamente cualquier trabajo asincrónico) necesita uno?

Eso me lleva a mi punto, comparar motores en sus diferentes etapas de desarrollo es difícil y, de hecho, Godot está evolucionando rápidamente y agregando/eliminando funciones. Eso significa que nuestro flujo de trabajo tendrá que cambiar y adaptarse en consecuencia. Tengo un flujo de trabajo 2D decente con Godot, definitivamente es mejor que el que tenía con Unity. Sí, las mejores prácticas están turbias. Sí, si le preguntas a tres desarrolladores, tendrás tres flujos de trabajo diferentes. Pero no puedo decir que sea un problema nuevo para mí, o al menos está presente en los dos motores comparados.

Realmente no he usado Unreal (o cualquier otro motor de juego relevante) para más que prototipos y proyectos de prueba, no puedo compararlo con una profundidad razonable.

¿Pero de qué manera?
Ya sé que no puedo hacer un niño para cada script porque necesitaré más de un millón de funciones e incluso un millón de nodos vacíos es demasiado para Godot.
¿Qué significa eso, cuántas funciones deben agruparse o debo pasar de 2 a 4 meses planificando la herencia de mi objeto en papel?

¿Poner todas las funciones en un script quizás? Godot se puede usar orientado a objetos bastante bien, por lo que si alguna vez usó OOP, puede usar secuencias de comandos o herencia de escenas, crear clases, etc.

Lo que quiero saber es ¿cómo lidia Godot con juegos grandes con sistemas complejos como efectos climáticos, niebla volumétrica y terrenos grandes?

¿Efectos del clima? Cree una escena que contenga un nodo de partículas, un sol y un entorno mundial y adjunte un script a la raíz. Este script puede controlar el clima. También puede crear un nodo vacío y usarlo como una máquina de estado, adjuntando nodos vacíos para cada estado que tenga (como lluvia, sol, etc.). Ahora simplemente coloque el código para cada estado en sus nodos. Esta máquina de estado puede ser controlada por el script raíz. Esta es una manera muy fácil de leer de hacer las cosas.

¿Niebla volumétrica? Creo que he visto esto en la nueva demostración de FPS.

¿Grandes terrenos? Una vez tuve un proyecto con mallas de terreno de procedimiento y funcionaba bastante bien en mi computadora portátil de un par de años.

Sin embargo, estas son solo algunas funcionalidades en lugar de un "gran problema" del que hablaba en el OP.

¿Efectos del clima? Cree una escena que contenga un nodo de partículas...

Bueno, planeamos ser un poco más ambiciosos que eso :) con un mapa de la región para decirle a la IA dónde caminar y luego usar otro canal para las zonas de exclusión de lluvia mientras mantenemos el último canal para la profundidad para que la nieve pueda acumularse con el tiempo.

¿Grandes terrenos?

Espacio grande. Necesitamos alguna forma de restablecer las escenas al Vector3 (0,0,0) sin que se congele porque es necesario eliminar demasiados nodos. La física y todo se estremece con grandes flotadores.

tiene componentes tan inflados que no se puede comparar con ningún otro ECS que haya usado.

De acuerdo, los componentes pueden ser horribles, por eso no nos sorprendería si Godot tiene una estrategia diferente en mente. Sin embargo, no tenemos idea de qué estrategia planeó Godot o si lo hizo.

2 meses de aprendizaje Godot solo nos ha pensado como hacer pequeños juegos.
Con 14 días para decidir usar Godot, espero que los desarrolladores del motor puedan explicar cómo se supone que funciona en proyectos grandes.

Lo último que queremos hacer es pelear cuesta arriba contra el diseño de los motores mientras tratamos de desarrollar el juego.

@MysteryGM Realmente no entiendo por qué crees que Godot no se puede usar para grandes proyectos. Su diseño realmente se presta para grandes proyectos porque puedes dividir todo en escenas separadas y usar OOP para reutilizar el trabajo. Si su problema con el uso de Godot para un gran proyecto es que no sabe cómo lograr un objetivo, solo pregunte en los canales de ayuda de Godot Discords, obtendrá una respuesta muy inmediata.

La física y todo se estremece con grandes flotadores.

Ver #288

Sin embargo, no tenemos idea de qué estrategia planeó Godot o si lo hizo.

Entiendo que es un poco extraño al principio, pero para mí el uso de nodo+script es bastante sencillo. Definitivamente recomendaría echar un vistazo a (al menos) la versión de hobby de este curso aquí: https://gumroad.com/gdquest
Utiliza una estructura de script de nodo muy similar a la mía, y definitivamente puede brindarle una mejor idea de cómo lo usan aquellos que realmente están involucrados con el motor; el autor es uno de los principales contribuyentes a los documentos de godot.

edit: en realidad, puedes echar un vistazo a la fuente en el repositorio, si no quieres el curso https://github.com/GDquest/make-pro-2d-games-with-godot

Con 14 días para decidir usar Godot, espero que los desarrolladores del motor puedan explicar cómo se supone que funciona en proyectos grandes.

Supongo que estoy un poco confundido sobre lo que quieres decir exactamente con esto. Anteriormente usó la analogía del martillo como ejemplo, pero es una analogía defectuosa ya que un martillo es generalmente una herramienta utilitaria básica de un solo uso, y hay una comprensión intrínseca de para qué se usa la herramienta debido a su capacidad.

Además, si bien ha enumerado todos los problemas con todos estos sistemas anteriores, creo que la realidad de cualquier gran proyecto de software es que cada 'elección' de arquitectura que haga conducirá a algunas desventajas en el futuro, que solo tiene que trabajar más con en el camino. Entonces, ¿estás buscando una sugerencia bala de plata? Porque, francamente, ni siquiera creo que la mayoría de los proyectos de Unity o Unreal sigan la estructura 'recomendada' exacta y, a menudo, bifurcan el motor para que se adapte al flujo de trabajo que funcione mejor para ellos. Incluso iría tan lejos como para argumentar que cada juego debe tener su propia idea única sobre la arquitectura de nodos. (Un juego de simulación tendría una estructura muy diferente a la de un shooter en tercera persona, por ejemplo).

Supongo que se podría argumentar a favor de más documentación sobre ejemplos de la estructura del proyecto, pero creo que eso es solo una cuestión de más contribuciones a la documentación.

separe escenas y use OOP para reutilizar el trabajo.

Como mencioné antes, mover objetos después de que se hayan conectado las señales es una molestia. Especialmente cuando dejan de funcionar sin dar una excepción o advertencia.
Decidimos optar por una herramienta de refactorización de terceros, después de que otro desarrollador lo mencionara; pero aun así no puede resolver los problemas únicos de Godot.
No mover las cosas da como resultado este problema (imágenes de nuestro "tablero de problemas"):
pawndefend
Entonces, para solucionar esto, creamos nodos secundarios. Excepto que alrededor de 50 000 comienza a causar problemas, incluso si son solo nodos.
pawnfollow

Lo que queremos saber es cómo trabajamos con estos problemas, cómo planeó Godot lidiar con ellos; Probamos todos los flujos de trabajo que mencioné anteriormente.

Ver #288

Gracias por eso, estamos tan acostumbrados a las coordenadas del mundo en reposo, nunca verificamos esto.

Entiendo que es un poco extraño al principio, pero para mí el uso de nodo+script es bastante sencillo.

El problema no es que sea ajeno, el problema es que provoca un problema diferente. Principalmente que añadir más niños acaba por retrasar el juego o congelarlo cuando intentamos descargarlos.
Incluso cuando son solo nodos.

¿Por qué necesitas 50.000 objetos en tu juego? Seguramente esto retrasaría CUALQUIER motor.

¿Por qué necesitas 50.000 objetos en tu juego?

Porque usamos nodos para agregar scripts adicionales a los objetos. Porque las herramientas de interfaz de usuario de Godot usan contenedores en contenedores en contenedores... para escalar cosas en tiempo real.
Nuestra interfaz de usuario más pequeña tiene más de 800 objetos. La mayoría de estos contenedores.

Tenemos 50 000 objetos porque una sola IA enemiga tiene +/- 8 nodos con un propósito y +/- 64 nodos que solo están allí para que podamos adjuntarles scripts.
Porque al dividir cada tarea en su propio código podemos ver dónde están nuestros problemas. Porque no hay otra forma de encontrar rápidamente una parte específica del juego.

En ese caso, parece que ha entrado en la zona donde los módulos personalizados son una buena opción.
http://docs.godotengine.org/en/3.0/development/cpp/custom_modules_in_cpp.html
Puede crear nodos personalizados allí y evitar muchos anidamientos.

editar: aunque diría que 800 objetos para uno (¿el más pequeño?) ui apunta hacia un mal diseño/arquitectura.

Realmente no entiendo cómo puede tener cerca de 64 scripts para un solo objeto. Esto suena más a un problema de diseño de su proyecto que a un problema de Godot (nuevamente, es probable que retrase cualquier motor). Consolide su código en menos scripts. No haga un script para cada parte de la funcionalidad, sino para cada tipo de objeto (si un nodo "Enemigo" puede hacer XYZ, entonces agregue esa parte al script Enemy en lugar de agregar nodos secundarios para la funcionalidad X, Y y Z) . Si necesita funciones más avanzadas para hacer esto, tal vez podría utilizar la herencia personalizada y/o las interfaces de C#.

En ese caso, parece que ha entrado en la zona donde los módulos personalizados son una buena opción.

Mira, esta fue una de las cosas que nos preguntamos, porque todos sabemos C ++ si se necesita Custom Modulse, en su lugar, simplemente editaríamos el motor Godot.
Sabemos que podemos usar con seguridad #include donde la precarga de Godot() es cuestionable; nadie puede decirnos qué tan estable es o si hay alguna desventaja.

Realmente no entiendo cómo puede tener cerca de 64 scripts para un solo objeto.

Simple, cada IA ​​puede hacer más o menos 64 tareas, tampoco tareas menores.
Un script, por ejemplo, es SquadFlightPatters y aquí están todas las formaciones de vuelo, las 20, luego está SquadFlightPattersCosmetic que solo resuelve animaciones, sonido y partículas relacionadas con patrones de vuelo.

Nuestra regla en este momento es dividir los comentarios de los usuarios de los mecánicos.

Si un nodo "Enemigo" puede hacer XYZ, agregue esa parte al script Enemigo en lugar de agregar nodos secundarios para la funcionalidad X, Y y Z

Si miras las imágenes y Pseudo Unreal, también conocidos como controladores e intermedios.

Debido a que todos conocemos C++, si se necesita Custom Modulse, simplemente editaríamos el motor Godot.

Encuentro que crear módulos es mucho más simple que cambiar el motor en sí, ya que se construye sobre él, en lugar de dentro de él.

Sin embargo, todavía no puedo imaginar esta escala a números tan altos, especialmente la interfaz de usuario con cientos o miles de nodos por widget.

En respuesta a los problemas mencionados en OP:

  • 19486 :

    • agregue una gestión de dependencia adecuada con instalaciones de activos en todo el sistema. Mueva los complementos fuera del proyecto en sí mismo con una forma de recuperarlos para modificarlos
    • facilitar la extensión de nodos personalizados, permitir la herencia de scripts entre idiomas
    • permita que se haga referencia a los scripts por nombre de clase y espacio de nombres para evitar rutas muy largas en el caso de los activos.

    Las clases de script resuelven el último problema. Los espacios de nombres se pueden crear mediante la creación de una clase de secuencia de comandos de nivel superior con constantes que sirven como alias para otras secuencias de comandos. Los cambios que he realizado en el panel de escenas del editor en 3.1 también hacen que ahora sea MUCHO más fácil extender scripts personalizados. En cuanto a la herencia entre idiomas, eso nunca se implementará formalmente, pero si los MultiScripts alguna vez se vuelven a introducir, entonces podrían falsificarlo razonablemente bien.

  • 7402: Una vez más, las clases de script son la solución a este problema (la "solución más simple" en la que había pensado reduz, si ve algunos de los comentarios finales de este número).

  • 15996: Este era yo al darme cuenta de que lo que había querido era un sistema de rasgos (antes de entender qué eran los rasgos) y, en consecuencia, darme cuenta de lo absolutamente terrible que era mi propuesta inicial, ya que distorsiona por completo el diseño específico de escenas y nodos y convierte todo el cosa en un sistema de herencia basado en la composición, algo más parecido a lo que hace Unity en realidad, lo cual es repugnante (en Unity, puede usar getComponent de cualquier COMPONENT y obtiene el componente hermano en el GameObject propietario. Los componentes son, en la práctica, un extensión de GameObject, empujando sus dependencias entre sí).

  • 8502: MultiScript son simplemente herramientas para permitir que diferentes lenguajes de secuencias de comandos se hereden entre sí, de forma similar a la forma en que los Blueprints de UE4 pueden heredar directamente de las secuencias de comandos C++ (que, en Godot, no sería posible ya que la comparación es tener un GDScript que extienda un NativeScript. VisualScript ni siquiera admite la herencia en primer lugar, por lo que GDScript es la comparación más adecuada aquí).

    Ahora, dado que MultiScript esencialmente admite CUALQUIER secuencia de comandos que amplíe el tipo de motor base (por lo que podría tener múltiples secuencias de comandos de extensión de nodo de diferentes idiomas que hacen cosas diferentes, pero no están relacionadas entre sí), en realidad funciona casi más como un sistema de rasgos entre idiomas... más o menos. Sin embargo, creo que volver a agregar MultiScript sería genial

Muchas de las cuestiones planteadas en el OP giran en torno a la existencia de múltiples formas potenciales de abordar un problema, cada una de las cuales puede tener varias ineficiencias. Por lo general, cuando hay una forma particular de hacer algo que sería más óptimo, el motor proporciona su propia implementación en el motor principal de C++ (sin necesidad de scripts o complementos) y ese es el uso sugerido.

Si existe una clase de este tipo y las personas no la están usando, entonces eso es una señal de que 1) no están revisando correctamente la documentación para ver si el motor ya satisface sus necesidades / cómo sugiere el motor que se use o 2) el motor/la organización no está haciendo un buen trabajo al hacer que la documentación sea muy visible o accesible para los usuarios (ya que no encuentran los recursos que existen).

Lo único que se debe hacer para solucionar el problema 1 es que esas personas expresen su problema y que otra persona los redirija al sitio de documentos o preguntas y respuestas para ayudarlos a encontrar la solución. Creé un Problema (#23043) que sugiere permitir que las personas naveguen y usen el sitio de preguntas y respuestas directamente desde el editor, lo que debería ayudar mucho con el problema 2. Las razones se describen en el enlace.

(Editar: si hay muchas formas de resolver un problema, y ​​una de esas formas es mucho mejor que cualquier otra, y Godot aún no implementa su propia solución nativa, entonces eso sería algo para sugerir como una nueva característica para el motor Así es como agregamos el material SimplexNoise ya que las personas estaban escribiendo sus propios algoritmos SimplexNoise en código GDScript / shader, etc.).


Según el "tablero de problemas" que describió, el problema que tenía es que la herencia múltiple no es compatible (ni es una buena idea), por lo que optó por nodos de componentes que otorgan funcionalidad a su padre (lo que me parece razonable). Si tiene problemas con el retraso de su juego porque simplemente está creando demasiados nodos, entonces me parece que es muy probable que haya un problema con su enfoque general (que es lo que parece estar reconociendo y buscando ayuda para identificar aquí).


En cuanto a sus ejemplos de flujos de trabajo en OP...

  • Enfoque de unidad, nodos secundarios:

    Tiene sentido usar nodos secundarios, asumiendo que uno escribe lógica de emparejamiento. Idealmente, aquí es donde sería útil un sistema de rasgos (para que uno pueda escribir la lógica de emparejamiento una vez y simplemente replicarla en todas partes según sea necesario). A menudo escribo componentes de manera que se configuran automáticamente como "objetivos" para sus padres cuando tienen/no tienen padres y se conectan/desconectan automáticamente las señales relevantes. Puede usar las notificaciones NOTIFICATION_(UN)PARENTED en _notification(what) para esto.

  • Enfoque UE4 con controladores:

    Godot 3.1 le permite asignar clases de script para scripts, por lo que ya no es necesario precargarlos. En este caso, Godot SÍ le permite asignar nombres de tipo a los nodos, pero es específico del script, por lo que debe tener cuidado. Las escenas no reciben el mismo tratamiento, y probablemente no lo harán, ya que implicaría agregar un montón de cosas al núcleo del motor (que los desarrolladores del núcleo pueden ser bastante sensibles).

    Tampoco estoy seguro de cómo obtienes tanto código duplicado. Si varias clases requieren la misma lógica, agrupa esa lógica en un solo nodo y luego reproduce ese nodo en las clases que lo necesitan, de la misma manera que lo haría con Unreal (componentes, Actores secundarios), Unity (MonoBehaviours o GameObjects secundarios) , o prácticamente cualquier otro motor que cambie las dependencias a un objeto propio para reducir la reutilización del código.

  • Enfoque Panda3D con precargas:

    Podría entender que haya muchos problemas con este enfoque, ya que NodeRefs aún no existe, y hay problemas con la exportación de scripts de recursos en este momento que espero solucionar para 3.2 (aunque probablemente podría solucionarlo usted mismo). con bastante facilidad, es bastante pequeño).

  • Enfoque de guión WTF:

    Realmente no entiendo todos los problemas que están teniendo aquí, probablemente porque no tenemos mucho contexto.

    Conflictos con el sistema de instancias. Porque las instancias fluyen hacia abajo mientras que la señal se conecta mejor hacia arriba.

    ¿Cuándo le gustaría tener el comportamiento de activación de la señal de un padre en un descendiente? ¿Por qué no hacer que el padre obtenga y llame directamente al descendiente y su método? No hay peligro de que el padre vea a su hijo. Es como decir que un objeto C++ no debería poder acceder a su estructura o variables miembro de clase (?).

    Pequeños guiones sin sentido simplemente merodeando. Todo lo que hacen es enviar una señal y rastrear un solo valor.

    Esto ya es una señal de que el diseño del proyecto no es bueno. Es el problema de que cada interacción singular en el juego sea rastreada por su propio objeto personal. Esto no es realmente ideal, desde cualquier perspectiva.

    Mover un objeto con tantas señales adjuntas es frustrante en lo más mínimo.

    ¿En qué manera? En general, descubrí que estoy codificando las conexiones en el archivo de escena o conectando y desconectando algorítmicamente las señales de los nodos si están destinados a moverse. Eso ha servido bastante a mis propósitos, pero si tienes problemas específicos, compartirlos puede ayudar a otros a ayudarte.

    Las señales y los grupos permiten que partes completas del juego fallen, sin siquiera una advertencia.

    Este es el problema con cualquier booleano a través del diseño de existencia. La alternativa es recorrer TODOS los objetos, verificar si coinciden con los criterios y luego hacer la lógica si coinciden y, si coinciden, pero no correctamente, arrojar un error. En el caso de las señales y los grupos, los comportamientos se activan automáticamente en todo lo que está dentro del conjunto, por lo que si algo se sale del conjunto, no hay forma de detectar que se ha producido un problema durante el tiempo de ejecución. La única forma de encontrar problemas de este tipo es durante los procesos de configuración, donde los grupos/señales se organizan en primer lugar.


De todos modos, esa fue toda mi experiencia con las cosas. Nos ayudaría mucho más saber más sobre su proyecto y lo que realmente está haciendo para que podamos darle sugerencias para su caso de uso particular.

De cualquier manera, los problemas que ha planteado aquí no parecen ser problemas "nuevos" con el diseño o la implementación de Godot Engine per se. Godot le da a la gente una API y cómo la gente usa esa API depende de ellos. Si tiene una idea de cómo una función en particular debería estar más integrada/disponible en Godot (por ejemplo, revitalizar MultiScript), entonces esa sería una buena propuesta.

Sin embargo, tal como está, la pregunta aquí parece ser más bien "cuál es la mejor manera de diseñar un sistema como X" que... no es realmente un problema de GitHub. Parece más apropiado en el sitio de preguntas y respuestas para un tipo de pregunta de "mejores prácticas". Eso, o es una sugerencia de que deberíamos proporcionar una vía para hacer que este tipo de información específica de casos de uso sea más clara/disponible públicamente, que es exactamente de lo que trata mi problema de preguntas y respuestas.

Las clases de script resuelven el último problema.

Primero, gracias por la larga respuesta, eso es mucho y claramente tomó algo de tiempo escribirlo.
Me complace escuchar acerca de las clases de script, no usamos 3.1; solo para ejecutar la demostración de FPS.

pero si los MultiScripts alguna vez se vuelven a introducir, entonces podrían falsificarlo razonablemente bien.
Es completamente comprensible que Godot nunca implemente MultiScripts. En verdad, solo estaba señalando que muchos de los usuarios de GitHub buscaron soluciones de flujo de trabajo similares a las que probamos.

¿Cuándo le gustaría tener el comportamiento de activación de la señal de un padre en un descendiente? ¿Por qué no hacer que el padre obtenga y llame directamente al descendiente y su método?

Siento que debería explicar esto. En ese momento teníamos scripts muy grandes, cada uno con aproximadamente +/- 30 funciones. Por esa razón, queríamos evitar agregar funciones de señal adicionales al script ya de por sí extenso.
El resultado fue que creamos guiones sueltos para descargar el trabajo del guión grande.

Esto ya es una señal de que el diseño del proyecto no es bueno.

Esa es de hecho la raíz del problema. Principalmente que probamos muchos diseños recomendados por la comunidad de Godot y algunos de tutoriales.
1.) Al principio teníamos herencias locas, rápidamente abandonadas cuando se hizo evidente que guardar la escena de la rama o mover un objeto a otra escena desconectaba las señales.
2.) Seguimos esto con guiones grandes. Excepto los nombres abstractos de estos scripts para tratar de explicar lo que hace cada uno, dificultaba encontrar problemas.
Sabíamos cuáles eran los nombres de las funciones que causaban problemas, pero no exactamente dónde estaban ubicadas.
3.) Luego, al leer el manual, encontramos el enfoque del nodo secundario. Quizás era demasiado tentador porque permitía nodos directos y podíamos ver la estructura en el editor; también filtrarlo para encontrar el guión exacto que queríamos.

Terminando conmigo aquí, y creo que la última respuesta abordó mucho de lo que me preguntaba; Tendré que verificar dos veces mañana ya que aquí son las 2 a.m.

"¿Cuál es la mejor manera de diseñar un sistema como X?" que... no es realmente un problema de GitHub.

Quiero señalar que agotamos la mayoría de nuestras otras opciones. Cada uno de nosotros preguntó en los foros de preguntas y respuestas, hicimos amigos en la comunidad y recopilamos ejemplos de ellos. Escaneó los documentos en busca de explicaciones.
Todos los flujos de trabajo que describí son cosas que probamos y nos explicaron los usuarios de Godot, que usan estos flujos de trabajo. Cada uno funcionaría en los motores mencionados, pero no funcionaron tan bien en Godot.

Solo el último flujo de trabajo funcionó, excepto que nuestro programador principal se golpeó la cabeza contra la mesa y fingió estrangular a alguien.

Lamento leer que tiene problemas para encontrar soluciones a sus problemas. Will ya le dio una respuesta larga, así que intentaré no desordenar demasiado la conversación, pero en este punto, parece que necesitaría más de un consultor para ayudarlo a resolver los desafíos específicos que surgieron de sus necesidades.

Principalmente que probamos muchos diseños recomendados por la comunidad de Godot y algunos de tutoriales.

La mayoría de nosotros en la comunidad trabajamos en proyectos de una escala relativamente pequeña. Utilizo muchos nodos para ayudar a transmitir el punto y la estructura de un sistema determinado en los tutoriales. Esto escalará bien para la mayoría de las personas. Pero lo que funciona para un juego pequeño o mediano no se aplica a los más grandes.

Siguiendo lo que @willnationsdev dijo anteriormente, podría valer la pena considerar el código de back-end para ayudar a escalar el juego, tanto en términos de rendimiento como solo para tener menos código para administrar en el propio editor. No puedo ayudar mucho además de eso ya que, como muchos aquí, no tengo experiencia con proyectos más grandes. ¡Buena suerte!

Hola, solo tenemos una pregunta más.

Si tenemos dos objetos no relacionados, como un edificio y agua, pero queremos que los scripts de estos objetos interactúen, ¿cómo hacemos esto sin nodos ni precarga?
El agua es una textura por lo que tampoco puede chocar con el edificio.

@MysteryGM ¿Está diciendo que no quiere nodos que representen el edificio y el agua, o simplemente no quiere que se les adjunten guiones? No hay nada de malo en tener datos para procesar que no existen de alguna manera dentro del árbol de la escena aparte de un solo nodo que contiene datos.

Si desea adoptar el enfoque de ECS, en lugar de adjuntar secuencias de comandos a cada instancia de un tipo y hacer que se procesen individualmente, puede tener un solo nodo de "sistema" que recorrerá en iteración y realizará el procesamiento en los nodos de acuerdo con un tipo/ grupo que les asignó. Si desea evitar adjuntar secuencias de comandos a los nodos para su información detallada individual, también puede almacenar esa información en el sistema dependiendo de qué tan temporal. Esto mantiene sus nodos más livianos y puede ser más eficiente para usted cuando opera en miles de entidades del mismo tipo.

Con tener 50.000 de cualquier cosa , ha superado durante mucho tiempo el punto en el que la metáfora basada en objetos SceneTree-and-nodes de Godot es útil.

Eso no es muy diferente de otros motores, con Unity alcanzaría límites similares con sus objetos de juego, GC, o con UE4 encontraría problemas para escalar planos tan lejos, pero sobre todo , tener esa cantidad de cualquier cosa significa el valor predeterminado. los editores visuales simplemente ya no son útiles y las herramientas proporcionadas comienzan a fallar o al menos funcionan mal.

En todos los motores, la solución es básicamente la misma: construya sus propias soluciones. Lo que son depende más de tu juego, arquitectura y los detalles que del motor.

Clases de administrador, buses de comunicación pub-sub, intermediarios de mensajes, administradores de instancias similares a lo que se hace para partículas, grupos de objetos, sombreadores personalizados para descargar trabajo a la GPU, sombreadores de cómputo, mover el procesamiento a subprocesos u otros procesos/servidores: hay toneladas de bloques de construcción para posibles soluciones, y cuáles necesitará combinar dependen de su conjunto de problemas específicos.

Unity facilita algo de esto con su nueva infraestructura de ECS. No estoy seguro acerca de UE4. Sin embargo, al final, en este nivel avanzado, tendrá que hacer la mayor parte del trabajo pesado usted mismo (o contratar a alguien con experiencia para que lo haga por usted).

UE4 y Unity solo son más fáciles en la medida en que son más antiguos, están más establecidos y, por lo tanto, hay una mayor cantidad de personas que se han topado con problemas de escalamiento, lo que significa más conocimiento (y talento contratable) disponible para resolverlo.

Pero realmente, al final, ningún motor te llevará tan lejos. Todo juego ambicioso se encontrará con limitaciones en cualquier motor. Conozco decenas de ejemplos de juegos medianos y grandes en UE o Unity que también necesitaban resolver problemas similares. O resuélvalos o reduzca su alcance.

Lo que los desarrolladores de juegos de Godot necesitan de los desarrolladores de Engine es una clara desaceleración de lo que es el flujo de trabajo oficial para crear objetos y sistemas complejos.

Eso depende en gran medida de tu juego. No hay una respuesta directa para esto en ningún motor grande.
¿Deberías usar el enfoque basado en escenas de gameobjects en Unity? ¿O el ECS híbrido? ¿El nuevo ECS completo? ¿Qué tubería de procesamiento usas?
¿Irás con Blueprint o C++ en tu proyecto UE4?

Todos los motores ofrecen toneladas de opciones, toneladas de flujos de trabajo y mucha libertad, porque no existe una solución única para todos.

Entonces , si necesita consejos concretos sobre cómo abordar su juego específico en Godot, cómo estructurarlo, qué arquitectura usar, deberá proporcionar mucho más contexto e información.

Díganos lo que quiere lograr, y tal vez alguien pueda intervenir con un consejo. Si no, la única forma puede ser contratar a un desarrollador Godot experimentado como consultor.

Solo puedo estar de acuerdo con Groud:

Todas las soluciones tienen compensaciones, por lo que no tiene sentido crear un flujo de trabajo "oficial".

@mhilbrunner Solo hago de abogado del diablo aquí, pero un mejor diseño del motor (como un ECS adecuado en la mayoría de los casos en los que el rendimiento es importante) hace que muchos de esos límites sean significativamente más altos de lo que casi cualquier juego experimentaría (así es como el nuevo Rust Amethyst el motor del juego se está construyendo para enfocarse en, por ejemplo).

Pero sí, hice algo similar a ECS en Godot (2) y funcionó mucho mejor que el estilo de creación de instancias de scenetree en términos de eficiencia y distribución de funcionalidad. Se puede hacer, solo un poco doloroso ya que Godot carece de algunas primitivas útiles para ello.

@OvermindDL1

Solo puedo hablar por mí mismo, no por otros desarrolladores de Godot, y solo tengo experiencia con UE, Unity y Godot, así que no sé sobre Rust Amethyst.

Se puede hacer, solo un poco doloroso ya que Godot carece de algunas primitivas útiles para ello.

Tener una discusión sobre dónde tendría sentido agregar tales primitivos / cómo Godot puede acomodar mejor esos casos de uso sería muy valioso, creo. Tal vez no en este número :)

Pero deberíamos recopilar estos comentarios de alguna manera.

Y estoy de acuerdo en que existen diferentes límites según el motor, pero nuevamente, he visto a personas chocar con barreras similares en Unity y UE4 también. Tal vez más tarde, tal vez esos fueron más altos, pero al final, deberá poder resolver los problemas que encuentre en cualquier motor. :)

@MysteryGM ¿Está diciendo que no quiere nodos que representen el edificio y el agua, o simplemente no quiere que se les adjunten guiones?

Ya tengo un script adjunto al objeto de agua que alimenta el sombreador de agua. Entonces ya no puedo adjuntar un script al nodo de agua.
Tengo un script adjunto al edificio que controla su producción de recursos y conecta cosas como puertas. Entonces, también tiene un script al que no quiero agregar más código.

Con ambos objetos que ya tienen código, ¿qué hago ahora? No puedo agregar más nodos y aún no está claro si la precarga es una posible solución.

Mi pregunta si lo expreso como un diseño OOP es: ¿Cómo acceden dos scripts a las interfaces de los demás?

El problema es que GDscript no parece tener ninguna forma de acceder a otros scripts directamente.
Si quiero que Fuego queme Madera, tengo que tener Madera->extender->Fuego o Fuego->extender->Madera.

@MysteryGM : Un consejo: señales. El fuego puede tener una quemadura de señal (objetivo) donde el objetivo es su madera.

¿Cómo acceden dos scripts a las interfaces de los demás?

$NodeWithScript.do_function() ?

_/yo todavía estoy jugando al abogado del diablo, no tomes esto como una medida de lo que 'debería' hacerse en Godot, en el mejor de los casos es bikeshedding_

Solo puedo hablar por mí mismo, no por otros desarrolladores de Godot, y solo tengo experiencia con UE, Unity y Godot, así que no sé sobre Rust Amethyst.

UE utiliza un modelo Actor SceneTree. Unity usó un modelo EC (aunque recientemente han estado construyendo un ECS y descartando el antiguo modelo EC, aún no está completo pero parece prometedor). Y Godot usa un modelo Component SceneTree. ECS es un subconjunto del patrón de flujo de datos (específicamente es una generalización del mismo).

Breve resumen sobre ECS:

  • Una ' E ntidad' es solo una identificación de número entero, aunque la mayoría de los motores empaquetan una generación y un índice de entidad en un único int32 (generación de 8 bits e índice de 24 bits) o int64 (32 bits cada uno, int64 es significativamente más común ya que ECS realmente le permite para escalar a cantidades tan significativas de entidades).

  • Un 'Componente' es una estructura POD en la terminología de C /C++, absolutamente nunca debería contener funcionalidad. En general, debería ser trivialmente memcpy'able.

  • Una 'Tabla' de componentes es el almacenamiento de componentes, en su forma más básica puede ser simplemente una matriz redimensionable, pero en general tienden a usarse algunos tipos:

    • Matriz redimensionable: a menudo se usa cuando un componente es extremadamente común, como una posición.
    • Array disperso: a menudo se usa cuando un componente tiende a usarse en grupos de entidades a la vez.
    • Mapeo: tal vez un mapa hash o un mapa de árbol dependiendo de las características de rendimiento que espera, pero generalmente se usa para componentes menos comunes.
    • Conjuntos de bits: se utilizan únicamente como definición de si un componente existe en una entidad pero no almacena nada, generalmente conocido como componente de bandera.
    • Octtree o algún otro SceneGraph (el renderizador de Godot podría encajar aquí): El mapeo de scenetree que pretende ser un componente.
    • Etc...: muchos otros tipos dependiendo del acceso y las características de rendimiento esperadas para un componente.
  • Un ' Sistema ' es, en su forma más básica, una función que toma un conjunto unido de componentes, aunque la mayoría de las bibliotecas lo tienen como una clase o módulo no virtual, opera sobre ese conjunto unido de componentes para 'hacer' algo, lo que podría involucrar cambiar valores en componentes, agregar o quitar componentes, etc. Algunos ejemplos:

    • Un sistema que toma todas las entidades con un componente de Posición y Transformación y transforma todas las matrices de posición con las transformaciones necesarias en el tick/tiempo dado de una manera eficiente y compatible con caché. Cuando no hay más transformación que hacer (una entidad se vuelve estática), el componente Transformación se elimina de la entidad y ya no se procesa.
    • Un sistema de entrada escucha los eventos de las entradas (mouse/teclado/gamepad/etc...) y los transforma en componentes que se agregan a las entidades relevantes o para realizar otras acciones.
    • Un sistema Furnace (metáfora de Minecraft) toma entidades que tienen Inventario, Combustible, Mapeo de Recetas, BlockPos, Cocinar y otros componentes, itera sobre esas entidades y actualiza los estados relevantes según sea necesario, hasta que no quede nada más para cocinar y cuando el combustible se agote, se elimina. el componente de bandera de cocina para que ya no se procese hasta que el inventario se cambie nuevamente para establecer cualquier componente de bandera.

Internamente, puede pensar en un ECS como una base de datos donde puede suscribirse para establecer mapeos de datos, aunque si están bien hechos, están extremadamente bien optimizados. Con el conocimiento de qué sistemas deben ejecutarse antes de qué otros sistemas y qué sistemas operan sin superposición (dependiendo de la lectura o la lectura/escritura), también puede realizar múltiples subprocesos en las llamadas. (Sigo usando Amethyst y su parte de la biblioteca específica de ECS llamada specs como ejemplo porque participé en su creación al transferir mi antigua biblioteca C++ ECS) El libro de especificaciones detalla mucho sobre 'Por qué' ECS, ' Cómo, eficiencia, usos, etc... Amethyst entra aún más en detalles, especialmente en cómo deben usarse los ECS con los sistemas generales de juego, renderizado, etc...

Si desea ver una biblioteca C++ ECS bien escrita, mire https://github.com/skypjack/entt de todas las bibliotecas C++ ECS que he visto que no hice, parece ser la mejor hecha en general (aunque las especificaciones aún lo superan en mis pruebas simples, aunque no por mucho, lo cual es impresionante considerando que las especificaciones superan todo con lo que lo he comparado por márgenes significativos).

El 'uso' general de ECS es que tiene una 'Entidad' (solo un número entero, sin datos), y tiene el conjunto de tablas que asignan componentes a entidades y los sistemas para realizar el trabajo. En el pseudocódigo de GDScript, me imagino que es una API simple, aunque con una convención un poco extraña para 'integrarse' en el árbol de escenas de Godot, ya que el árbol de escenas no fue diseñado con eso en mente.

# All of this would generally be wrapped up in one or more function calls for easy
# building.

# Create a new entity
var e = createEntity()

# Map it to some Components, starting with a godot scenetree component
# I'm using long names to be descriptive, but eh...
var eNode = scenetreeComponentTable.set(e, SomeNodeType())
# Generally things like the transformation matrix and so forth would be their own
# components, but since the godot scenetree already bakes all that in then just
# deal with it all via the node type, you definitely lose a little efficiency doing
# it this way though since nodes involve multiple virtual calls to access and
# the usual ECS patterns entirely get rid of virtual calls with potentially only
# the occasional indirect calls inside a table (maps, etc...)

# 8x4 inventory slots
inventoryComponentTable.set(e, 8, 4)
# 1 fuel slot, accepts items that have the "burn" tag
fuelStorageComponentTable.set(e, 1, "burn")
# Give this entity the furnace component that uses the "basicFurnaceRecipes" recipes
furnaceComponentTable(e, "basicFurnaceRecipes")
# Add other components

# All of the above component mappings could also be in, say, a JSON file, and
# loaded something as such:
componentTables.map(e, "res://entity_types/basicFurnace.json")
# Or maybe via a preloaded JSON object or so

# Once at startup:

# And you could make a system something like, I'll use a GDScript class for this:
val furnaceCookSystemHandler = systems.register(FurnaceCookSystem.new())
furnaceCookSystemHandler.staticTickRate(0.05) # 20 times a second exactly

# Where the `FurnaceCookSystem` could be something like:
class FurnaceCookSystem:
  def _entity_matchers():
    furnaceBurnMatcher =
      componentTables.matcher().
      write(inventoryComponentTable).
      write(fuelStorageComponentTable).
      writeEither(inventoryChangedComponentTable, furnaceCookingComponentTable)
      read(furnaceComponentTable)
    return [furnaceBurnMatcher]

  # Assume we have matching semantics here to destructure a list, I'm lazy...
  def _entities_process([furnaceBurnEntities], delta):
    # This function takes a list of entity sets in the same order as the matchers
    # returned above.
    while entity in furnaceBurnEntities:
      val furnace = furnaceComponentTable[entity] # or .get(entity) or whatever API
      val cooking = furnaceCookingComponentTable[entity]
      if cooking == null or cooking.cookTimeRemaining <= 0:
        if cooking != null:
          if inventoryComponentTable.put(item) == False: # No space, try later
            continue
        # Get next item that has a "burnable" tag, if any
        val item = inventoryComponentTable[entity].getAndRemoveFirstOf("burnable")
        if item == null:
          furnaceCookingComponentTable.remove(entity)
        else:
          cooking = furnaceCookingComponentTable.set(entity, item, furnace.cookTime * getCookTimeModifierOfItem(item))
      else:
        cooking.cookTimeRemaining -= delta

 # ... whatever other functions are useful to the system

# Then of course just with the right components on any entity it will just work
# 'as' a furnace.  You can have a whole variety of 'generic' systems that can be
# mixed and match with impunity.  If you want a random rock that can be a furnace
# then just add the proper components, or if you want an Ent that can both be
# chopped down like a tree for wood but will also attack the player then just add
# the proper components, etc.... etc....

@MysteryGM : Un consejo: señales. El fuego puede tener una quemadura de señal (objetivo) donde el objetivo es su madera.

Lo siento, quise decir scripts, no instancias. Quiero que los scripts interactúen sin necesidad de un nodo en el árbol de Godot.

Lo siento, quise decir scripts, no instancias. Quiero que los scripts interactúen sin necesidad de un nodo en el árbol de Godot.

Tal vez no estoy entendiendo bien su problema, pero estoy bastante seguro de que ya puede hacerlo creando clases en GDScript. Aún necesitaría una carga automática o al menos un script en un nodo para que sirva como punto de entrada.

Además, ¿has probado C#? Si está tratando de crear un sistema complejo que tenga secuencias de comandos que interactúen y controlen los nodos a través de algo más que adjuntar secuencias de comandos a los nodos, probablemente lo pase mucho mejor con C# que con GDScript para dicho sistema.

@MysteryGM Hacer que los scripts interactúen entre sí sin el uso de un nodo en la escena significa que debe obtener una versión cargada del recurso del script, como mínimo. La única forma de hacer esto en 3.0 es preload / load el script por ruta de archivo. 3.1 agrega la característica de "clase de secuencia de comandos" para GDScript y NativeScript donde los nombres dados a las secuencias de comandos se registran globalmente. GDScript luego convierte manualmente esos registros globales en el motor a variables globales en el idioma.

Luego, si tiene el recurso Script , puede llamar a métodos estáticos en el script o llamar a .new() para obtener un ScriptInstance y luego llamar a funciones miembro/acceder a variables miembro. Si Script está derivando Objeto, Referencia, Recurso u otro tipo que no sea de Nodo, simplemente crear una instancia de Script / ScriptInstance será todo lo que necesita para obtener el contenido estático/no estático. Si se trata de un nodo, se aplica lo mismo excepto para las cosas que requieren acceso a SceneTree (como get_node ), en cuyo caso tendrá que usar add_child para agregarlo primero a SceneTree.

Todo lo anterior se aplica a cualquier lenguaje de secuencias de comandos utilizado con Godot (aunque creo que la precarga es una operación específica de ciertos lenguajes...).

el script por la ruta del archivo. 3.1 agrega la característica de "clase de script" para GDScript

¿Cuándo se lanzará oficialmente 3.1?

@MysteryGM Cuando el porcentaje de finalización del hito es lo suficientemente alto / cuando los desarrolladores principales han juzgado que el progreso es lo suficientemente avanzado como para considerar que la compilación es "estable".

Hito: https://github.com/godotengine/godot/milestone/7

A modo de comparación, 2.1 y 3.0 se encuentran actualmente en un 99% de finalización. Sin embargo, no estoy muy seguro de si ese es el estado en el que se encontraban cuando se lanzaron.

Básicamente, la respuesta es "cuando esté listo".

Gracias por las respuestas y nos disculpamos por tomar su tiempo.
Parece que Godot no se ajusta a nuestras necesidades en ese momento. Tal vez en el futuro tengamos la oportunidad de usar el motor nuevamente.

Si quiero que Fuego queme Madera, tengo que tener Madera->extender->Fuego o Fuego->extender->Madera.

@MisterioGM
Ver aquí
La solución (sin importar el motor o el idioma) podría ser tener un script de "sistema" que controle las interacciones entre el fuego y el bosque. Esa presentación se centra en los componentes, pero también se puede hacer que un sistema funcione con objetos.

En C# podría decir que Wood implementa IBurnable que usa Fire .

Hola, gracias por la preocupación constante y estamos muy agradecidos por el apoyo de @willnationsdev . Creemos que los scripts como solución de recursos de exportación tienen mucho potencial. Como se menciona en #22660.

Debido a que todavía tenemos 10 días para decidir qué motor usar, hemos estado probando un poco más con Godot.
Hemos estado analizando los problemas de flujo de trabajo y creo que nuestro programador lo dijo mejor:

"Los desarrolladores de Godot mantienen cada problema en Github en su propia publicación, siempre abren un problema para un error , pero no permiten el mismo flujo de trabajo para su motor".
El hecho de que tenemos que hacer un script Y estamos obligados a agregarlo a la jerarquía.

script de "sistema" que controla las interacciones entre el fuego y el bosque. Esa presentación se centra en los componentes

Sí, eso es lo que queremos, ¿cómo lo hacemos en GDscript?

En C #, podría decir que Wood implementa IBurnable que usa Fire.

Godot tiene a Duck escribiendo para hacer lo mismo que Interfaces. Lo que queremos es que Burning sea una clase separada para que podamos reutilizarla, sin obligarnos a agregar un nodo a la jerarquía.

Lo que queremos es Fuego, Quema, Madera. No queremos Fuego (Madera+Quema).
La ventaja de este flujo de trabajo es que podemos depurar Burning por sí mismo, sin necesidad de arreglar Every object that can burn.

En C# simplemente declararemos Burning como su propia clase. Clase pública Burning y nuestro problema está resuelto.
En C++ incluiríamos Grabación y problema resuelto.

Sí, eso es lo que queremos, ¿cómo lo hacemos en GDscript?

@MisterioGM

Sin profundizar en las optimizaciones de rendimiento, todo lo que sugiero es mover la resolución de interacción a un script de sistema separado (no en fuego, no en madera). El sistema en el caso más simple puede contener matrices de todos los objetos del mundo y manejar sus interacciones. En este caso, los objetos no tienen que preocuparse por los tipos, solo el sistema se preocupa.

Para acelerar las cosas, solo se pueden realizar comprobaciones de los objetos que realmente colisionaron (por ejemplo, enviando un signal desde el objeto al sistema cuando se produce la colisión).

Algunos ejemplos específicos de GDScript para referencias cruzadas de scripts (para la versión 3.0):

Aquí Enemy actúa como el tipo/interfaz, se puede verificar con el operador is :

# Cache the enemy class.
const Enemy = preload("enemy.gd")

# Use 'is' to check inheritance.
if (entity is Enemy):
    entity.apply_damage()

Aquí runnerGame apunta a una escena _autoload_ (también conocida como singleton) con la ruta /root/runner:

onready var runnerGame = get_node("/root/runner")
onready var runnerScript = preload("res://runner/runner.gd")

func _ready():
    runnerGame.setMode(runnerScript.SPAWN_TITLE)

Aquí conectamos el signal "presionado" del botón al controlador (que podría estar en un objeto y script diferente, estamos usando self para referirnos al mismo):

func _button_pressed(which):
    print("Button was pressed: ", which.get_name())

func _ready():
    for b in get_node("buttons").get_children():
        b.connect("pressed", self, "_button_pressed",[b])

Consulte también los documentos aquí, hay algunas características más disponibles: http://docs.godotengine.org/en/3.0/getting_started/scripting/gdscript/gdscript_basics.html#inheritance

Consulte también los documentos aquí, hay algunas características más disponibles:

Gracias por tu aporte en el tema. El problema con la herencia es que solo funciona si conocemos todas las relaciones de las clases cuando las implementamos.

Aquí hay un ejemplo:

paso a
MeshInstance+ HomingScript = HomingMissile .
Pero ahora si quiero una mina terrestre teledirigida tengo un problema.
(MeshInstance+ ProximityScript) = Mina terrestre .
(MeshInstance+ ProximityScript) + HomingScript = ERROR más de un script
(MeshInstance+ ProximityScript) + (childNode + HomingScript) = ERROR ya que solo se mueve el nodo invisible.
(MeshInstance+ ProximityScript) + (childNode + ExtendedHomingScript) = ÉXITO ya que ahora ampliamos la clase Homing para que pueda poseer nodos del nodo secundario. Obtenemos HomingLandmine .

Excepto que ahora se puede argumentar que tanto Homing Missile como Landmine deberían extenderse desde HomingClass.

Paso B.
HomingMissile [de Homing]
HomingLandmine[de Homing] [+ ProximityScript] El script ahora está copiado y pegado en la mina terrestre.

Más adelante en la producción sucede lo mismo con otros guiones que tenemos.
Paso C.
Mina terrestre [de proximidad]
ProximityAlarm[de Proximity] [+ AlarmScript]
// HomingLandmine[from Proximity] [+ HommingScript] // Ahora nuestra mina terrestre también puede caber aquí.

Así que tenemos que continuar con el Paso A para encontrar la herencia adecuada para el Paso B. Sigue repitiendo este patrón yendo más allá de StepF, etc.

Encontramos una manera de prolongar el Paso A. Simplemente evitamos agregar un script al nodo superior y siempre lo convertimos en un nodo espacial o primario.
(Espacial + MeshInstance+ ProximityScript) + HomingScript = HomingLandmine
Excepto que este es el mismo problema pero con un ParentSpatial más caro; en lugar de childNode.

Me disculpo por lo largo que es esto.

@MisterioGM

"Los desarrolladores de Godot mantienen cada problema en Github en su propia publicación, siempre abren un problema para un error , pero no permiten el mismo flujo de trabajo para su motor".
El hecho de que tenemos que hacer un script Y estamos obligados a agregarlo a la jerarquía.
...
Lo que queremos es Fuego, Quema, Madera. No queremos Fuego (Madera+Quema).
La ventaja de este flujo de trabajo es que podemos depurar Burning por sí mismo, sin necesidad de arreglar Every object that can burn.
...
En C# simplemente declararemos Burning como su propia clase. Clase pública Burning y nuestro problema está resuelto.
En C++ incluiríamos Grabación y problema resuelto.

Lo que tienes que entender es que Godot no funciona de manera diferente en este caso. Si bien la solución principal es crear un subnodo con su propio script (para "Grabar" en este caso), puede simplemente definir Burning como su propia clase e incluirlo/usarlo a través de funciones estáticas (o instanciarlo y luego usar propiedades/métodos)

  • C++

    • clase Ardiente {};

    • incluir "quema.h";

    • Quemar::aplicar(leña, fuego);

    • Ardiendo *b = Ardiendo::get_singleton(); b->aplicar(madera, fuego);

  • C# (editado por cambios de estilo)

    • clase pública en llamas {}

    • usando Game.Burning;

    • Burning.apply (madera, fuego);

    • Burning b = Burning.Instancia; b.aplicar(madera, fuego);

  • GDScript (3.1)

    • extiende el Recurso # quema.gd

    • const Grabación = precarga("res://burning.gd")



      • en 3.0, puede usar un script común para cargar constantes para todos sus estímulos de uso común.


        extiende la referencia


        const Grabación = precarga("res://burning.gd")


        const Humectación = precarga("res://humectación.gd")


        extiende la referencia


        const Estímulos = precarga("res://stimuli.gd")


        # use Stimuli.Burning o Stimuli.Wetting


      • en 3.1, solo puede usar clases de script. Burning y Wetting no requieren "inclusión", ya que son globales.


        Además, si es reacio al uso global, podría hacer que "Stimuli" sea la clase de secuencia de comandos con las mismas declaraciones constantes, de modo que siempre esté disponible como un pseudo-espacio de nombres.



    • Burning.apply (madera, fuego)

    • var b = Ardiente.nuevo()

      b.apply(madera, fuego)

Para un enfoque de Unity/ScriptableObject, uno puede usar los scripts de recursos de Godot para el mismo propósito.

  • Los ajustes se pueden configurar en el Inspector.
  • Las "compilaciones" de la función se pueden guardar en un archivo para que ciertas configuraciones se puedan intercambiar fácilmente según sea necesario, incluso en tiempo de ejecución.
  • El editor crea automáticamente una instancia del Recurso en el Nodo utilizando la declaración de la escena, por lo que no es necesaria una actualización manual. Una matriz de dichos recursos podría funcionar razonablemente bien, aunque, con el sistema de sugerencias de tipo de matriz roto en 3.1 (hasta 3.2 con suerte), tendría que escribir un EditorInspectorPlugin para generar el contenido del Inspector correctamente (que es en realidad lo que estoy trabajando en mi repositorio de Godot-next FileSystemItemList (advertencia, es un WIP temprano), para ser utilizado en mi repositorio de Godot-Builder para matrices de archivos/directorios.

script de "sistema" que controla las interacciones entre el fuego y el bosque. Esa presentación se centra en los componentes

Sí, eso es lo que queremos, ¿cómo lo hacemos en GDscript?

La forma más fácil de hacer esto es con un nodo/escena de carga automática de algún tipo. La razón es que incluso si solo usa un nodo con toneladas de recursos para todos los diferentes sistemas (para minimizar la cantidad de nodos que está usando), probablemente querrá tener acceso a un Nodo que está en el árbol para que obtiene acceso al tiempo delta, datos de entrada, operaciones de rendimiento (especialmente combinadas con el uso de la señal), nodos de animación/interpolación/temporizador, y la lista continúa. Además, como una carga automática, GDScript nuevamente generará una variable global para el nodo para que se pueda acceder a los "sistemas" por nombre en cualquier parte de su base de código (otro reemplazo adecuado para usar una clase de script en este caso).

De hecho, tengo una gran refactorización de un antiguo complemento WIP, godot-skills , que me gustaría hacer y que creo que abarca esto y mucho más. Lea el (lo siento, largo) hilo de reddit sobre el tema. Se trata de examinar la viabilidad de utilizar subprocesos múltiples coordinados en una arquitectura de servidor (similar a la arquitectura subyacente de Godot) para implementar un sistema de interactividad igualmente genérico y reutilizable.

Por cierto, si alguna vez quieres chatear en tiempo real sobre el tema, no dudes en enviarme un mensaje privado en Reddit/Discord/Twitter, donde uso el mismo nombre de usuario.

@MisterioGM

MeshInstance+ HomingScript = _HomingMissile_.
Pero ahora si quiero una mina terrestre teledirigida tengo un problema.
(MeshInstance+ ProximityScript) = _Landmine_.
(MeshInstance+ ProximityScript) + HomingScript = ERROR más de un script
(MeshInstance+ ProximityScript) + (childNode + HomingScript) = ERROR ya que solo se mueve el nodo invisible.
(MeshInstance+ ProximityScript) + (childNode + ExtendedHomingScript) = ÉXITO ya que ahora ampliamos la clase Homing para que pueda poseer nodos del nodo secundario. Tenemos _HomingLandmine_.

Excepto que ahora se puede argumentar que tanto Homing Missile como Landmine deberían extenderse desde HomingClass.

Creo que me estoy perdiendo algo aquí. Afaik, la forma correcta de hacer un nodo de "comportamiento de componente" es uno que no se cambie a sí mismo, sino que modifique directamente un nodo "objetivo" donde el objetivo predeterminado es el padre. Esto evita el problema que está encontrando por completo, si no me equivoco.

extends Node
var src_target
export(NodePath) onready var dst_target = get_node(dst_target) if dst_target else null
func _notification(p_what):
    match p_what:
        NOTIFICATION_PARENTED:
           src_target = get_parent()
        NOTIFICATION_UNPARENTED:
           src_target = null
func _physics_process():
    # if necessary, can manually assign src_target elsewhere to be NOT a parent
    if src_target and src_target is KinematicBody2D:
        src_target.move_and_slide(...) # do logic to get parameters that move towards dst_target

Algo como esto significaría que no tiene que cambiar nada simplemente haciendo que un nodo con el script sea un elemento secundario de lo que desea que tenga la función de "ubicación". Solo tiene que asignar el valor de la propiedad exportada (ya sea en la escena o en el tiempo de ejecución) para indicarle a qué debe dirigirse. Se pueden usar otras propiedades exportadas para modificar el tipo de movimiento y esas cosas también se pueden subcontratar a un Recurso si desea tener diferentes "compilaciones". Una vez más, Godot te permite ser muy flexible con el diseño de tu framework de juego.

Algunas correcciones:

 - C#
-   - public class Burning {};
+   - public class Burning {}
    - using Game.Burning;
    - Burning.apply(wood, fire); // is it :: here? I forget...
-   - Burning b = Burning::GetSingleton(); b.apply(wood, fire);
+   - Burning b = Burning.GetSingleton(); b.apply(wood, fire);

No se necesita el punto y coma después de las llaves de cierre de la clase. Utiliza un punto para miembros estáticos en lugar de :: .
Como nota al margen, la convención para acceder a un singleton es usar una propiedad (generalmente denominada Instance ) en lugar de un método.

@neikeq Gracias. Estoy demasiado fuera de práctica con C#, lol.

En cuanto al enfoque de "Global Scripts", estoy muy en contra de esto. Alentaría a los desarrolladores a codificar su juego de mala manera. Una pregunta común de los desarrolladores de juegos Java y C++ desnudos anteriores, cuando prueban Unity/Unreal/Godot/etc, es "¿dónde está el bucle principal del juego en el que puedo escribir mi código?". Agregar un sistema de este tipo permitiría a esos desarrolladores hacer esto, por lo que podrían terminar escribiendo código en secuencias de comandos globales que hacen referencia a los objetos que desean modificar en lugar de simplemente usar una secuencia de comandos en un objeto.

Tal vez, en cambio, podríamos mejorar el rendimiento del nodo barebones Node para que no presente una sobrecarga para los "componentes" de objetos que solo contienen scripts. O tal vez incluso un nodo simple separado "solo contiene scripts".

@aaronfranke

En cuanto al enfoque de "Global Scripts", estoy muy en contra de esto. Alentaría a los desarrolladores a codificar su juego de mala manera. Una pregunta común de los desarrolladores de juegos Java y C++ desnudos anteriores, cuando prueban Unity/Unreal/Godot/etc, es "¿dónde está el bucle principal del juego en el que puedo escribir mi código?".

Como mencioné, si alguien no quiere hacer esto (razonablemente en un proyecto grande), entonces no hay problema con simplemente crear una clase de secuencia de comandos global de "espacio de nombres" que mantenga las constantes de otras secuencias de comandos para viajar más abajo en la jerarquía de la API. Aquí solo estamos hablando de scripts, no de referencias de nodos reales.

Agregar un sistema de este tipo permitiría a esos desarrolladores hacer esto, por lo que podrían terminar escribiendo código en secuencias de comandos globales que hacen referencia a los objetos que desean modificar en lugar de simplemente usar una secuencia de comandos en un objeto.

Este sistema ya es implementable por cualquier persona en Godot a través de cargas automáticas (no se sugiere "agregar" una función). Además, el problema que están encontrando en primer lugar es que no quieren agregar los sistemas en sí mismos como subnodos en el mundo (aunque también doy una sugerencia para eso en el comentario de seguimiento) ya que tienen tener tanto el nodo allí Y el script en ese nodo, y potencialmente refactorizar las relaciones entre todos los nodos y scripts cuando más tarde se den cuenta de que las cosas deben moverse.

Tal vez, en cambio, podríamos mejorar el rendimiento del nodo Node barebones para que no introduzca una sobrecarga para los "componentes" de objetos que contienen únicamente scripts.

¿En qué manera? La única forma de hacer esto de manera transparente sería implementar un sistema MultiScript y hay una gran cantidad de problemas que surgen junto con ese paradigma. La única otra alternativa que se me ocurrió al tratar de resolver ese problema fue el sistema de características de GDScript que sugerí en el n.º 23101, que limita los problemas de MultiScript a un idioma, pero viene con su propia serie de problemas aún más graves.

O tal vez incluso un nodo simple separado "solo contiene scripts".

Una vez que arreglemos el sistema de sugerencias de tipo de matriz en 3.2, podremos hacer esto con solo...

extends Node
export(Array, Script) behaviors = []

Incluso se podría implementar la característica ahora usando un Diccionario (para acceder a los scripts por nombre) y un EditorInspectorPlugin de 3.1 para definir una interfaz de usuario personalizada cuando esos nodos se abren en el Inspector (crear una interfaz de usuario de matriz de scripts exportada, pero tener agrega el script con una clave que coincide con el nombre de archivo debajo del capó).

extiende el Recurso # quema.gd

Ah, creo que encontré nuestro problema. Ninguno de nuestros intentos de precarga se extendía desde el recurso. No creo que ninguno de nosotros supiera que podíamos crear recursos personalizados.

También quiero señalar que nadie que compartió sus juegos con nosotros o que describió su flujo de trabajo se estaba extendiendo desde el recurso.
Casi todos estaban extendiendo Node. No tengo idea de la diferencia que esto hace, será necesario realizar pruebas.

FileSystemItemList (advertencia, es un WIP temprano)

Definitivamente tendrá que darle una mirada a esto.

@MisterioGM

No creo que ninguno de nosotros supiera que podíamos crear recursos personalizados.

¡Sí! Recientemente agregué una sección a los documentos que describe el proceso. :-D

Puede extender CUALQUIER tipo de motor con un script, incluidos Objeto, Referencia, Recurso y, por supuesto, Nodo (o cualquiera de las derivaciones de estas clases). Las únicas cosas que no se pueden ampliar son los singletons del motor y del editor (como OS, Engine o EditorFileSystem).

Gracias por tu aporte en el tema. El problema con la herencia es que solo funciona si conocemos todas las relaciones de las clases cuando las implementamos.

De nada. Pongo la herencia al final del comentario, porque no es necesaria para implementar el sistema de leña.
Parece que ya tiene una solución en mente usando paradigmas a los que está acostumbrado, y su problema no es cómo crear un sistema de leña, sino cómo usar los paradigmas favoritos.
Me disculpo entonces. No estoy familiarizado con la herencia de GDScript, pero creo que otros ya respondieron su pregunta.

Bien, hemos tenido algo de tiempo para probar el nuevo método y encontramos que funciona perfectamente. Ya pudimos reemplazar cientos de nodos con scripts; mejorando mucho el rendimiento.

Considerando que la precarga de Recursos soluciona el problema de Incluir scripts. También se puede usar como alternativa a MultiScript y ScriptableObject de Unity exportando una variable de recurso en GDscript.
Combinado con el hecho de que los Documentos se han actualizado para explicar los recursos con más detalle.
Sin mencionar que Godot 3.1 también tendrá clases de script que deberían permitir aún más flujos de trabajo.

Creo que el objetivo original de este problema se resolvió y ahora se puede cerrar.

Una vez más, quiero dar las gracias a todos por participar en la discusión, y especialmente gracias a @willnationsdev que proporcionó una gran cantidad de información sobre el motor de Godot.

@MysteryGM Creo que sus pensamientos al principio y al final de este hilo pueden ser buenos para escribir en un blog o en un borrador de Godot-docs. Creo que la mayoría de los primeros usuarios a menudo cometen errores de rendimiento cuando intentan lograr una organización compleja de secuencias de comandos, necesitamos buenos informes de "antes" y "después" en términos de aprendizaje. Las lecciones y patrones que aprendemos en los primeros tutoriales no se traducirán bien en juegos a gran escala, lo que para mí solo significa que necesitamos más blogs/consejos sobre lecciones a gran escala.

@pgruenbacher , es una gran idea. Hay dos problemas para nuestro equipo con esto, uno solo dos de nosotros sabemos inglés a un nivel útil, y el segundo es que tomará mucho tiempo.

Aun así, hay un buen cambio: haremos un blog de desarrollo y tomaremos notas de todo lo que descubramos. Es posible que hagamos una entrada de blog de "Transición a Godot".

En este momento estoy trabajando en algunos tutoriales en PDF del "Curso acelerado de Godot para artistas", porque queremos contratar trabajadores independientes para el equipo, pero Godot aún no es muy conocido.
Estos tutoriales tienen como objetivo presentar a Godot a los artistas de juegos profesionales.
Una vez que tenga estos hechos, los compartiré con los otros usuarios de Godot, los mantendré en formato PDF para empezar, porque es más fácil corregir errores mientras sigo aprendiendo.

@pgruenbacher @MysteryGM Si bien no está en la misma línea de una experiencia antes/después con Godot, este número y algunas preguntas recurrentes relacionadas me han llevado a comenzar a trabajar en un artículo de mejores prácticas de diseño de escenas/guiones para Godot-docs. Tengo una sucursal en mi bifurcación, pero es muy temprano en el cajero automático WIP.

Leer temas como este es extremadamente desalentador (en el sentido de hacerme dudar si elegimos el motor correcto). Nuestro proyecto tiene más de 15,000 LoC y está perfectamente organizado y funciona muy bien. (No voy a entrar en detalles de puntos específicos porque otras personas aquí son mucho más inteligentes que yo).
Dicho esto, ¡me alegra que te quedes con Godot, MysteryGM! Definitivamente estoy deseando leer el blog de desarrollo

Meh, en mi opinión, los juegos con una lógica significativa están mejor con el código
aislado del motor del juego de todos modos, por lo que realmente no debería importar cómo
el motor funciona Las secuencias de comandos de mi nodo se utilizan principalmente para la representación de la interfaz
y lógica física. La lógica del juego es una biblioteca compartida compilada por separado.

El miércoles 14 de noviembre de 2018, Aaron-Fleisher [email protected]
escribió:

Leer temas como este es extremadamente desalentador (en el sentido de
haciéndome verificar dos veces si elegimos el motor correcto). nuestro proyecto esta bien
más de 15.000 LoC y perfectamente organizado y funciona muy bien. (no voy a ir
en detalles de puntos específicos porque otras personas aquí son mucho más inteligentes
que yo mismo).
Dicho esto, ¡me alegra que te quedes con Godot, MysteryGM! definitivamente buscando
ansiosa por leer el blog de desarrollo


Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/godotengine/godot/issues/23052#issuecomment-438871197 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/ADLZ9pw2-G0kE19meyi7iSkceAldfAMjks5uvLb4gaJpZM4XelSe
.

@aaron-fleisher

... haciéndome dudar si elegimos el motor correcto

Si el motor que está utilizando ahora funciona para usted, incluso si tiene que hacer algún trabajo, entonces no hay razón para preocuparse. Es posible que algunos jugadores (u otros desarrolladores) cuestionen tu habilidad/cordura, pero esa es solo la realidad del desarrollo del juego. Mucha gente apasionada que habla con aparente autoridad (a menudo muy por encima de su nivel de habilidad real).

Eres tú quien conoce tus problemas, y eres tú quien va a tener que hacer el trabajo. Evite quedar paralizado por lo que le habría comprado tal vez otro 10% -20% de productividad. Guárdalo para el próximo juego. O no, ya que ya ha invertido mucho en aprender las herramientas que ya conoce. Tu elección :)

No sé, tengo la sensación de que los desarrolladores de Godot no saben lo que están haciendo.

Al usar Godot 3.0.6 estable por primera vez, se me presenta un "Administrador de proyectos" feo y disfuncional. Cuando incluso puedo averiguar cómo funciona (y no es nada intuitivo), la aplicación se bloquea cada vez que intento descargar un programa de ejemplo de la Biblioteca de recursos. A veces, la aplicación simplemente deja de responder. A veces, la aplicación arroja errores misteriosos de "condición! conectado es verdadero". A veces, la descarga se detiene. Y cada vez, un archivo de 100 MB tarda aproximadamente 10 minutos en descargarse en su mayoría, mientras que puedo descargar 10 GB en otro lugar en la misma cantidad de tiempo. "Reintentar" inicia la descarga completa desde cero.

Tengo la sensación de que "estable" aquí significa "lo arruinará siempre".

Hable acerca de una primera impresión decepcionante.

@dejayc Eso es extraño. Nunca he tenido problemas con Project Manager (con 3.0.6 estable o incluso con la rama maestra) en Windows 10 o mi dispositivo Linux Mint. Le recomendaría que creara un nuevo Problema sobre sus problemas aquí (ya que este no es realmente el Problema adecuado para un tema de este tipo) y, con suerte, alguien puede ofrecer una mejor asistencia.

@dejayc
Si todos hacemos una donación a Patreon, el proyecto Godot podría contratar al tipo de usabilidad a tiempo completo .

Si bien estoy de acuerdo con sus puntos menores, los motores deben elegirse en función de las publicaciones de marketing en las redes sociales, cuán críticos son sus inconvenientes para el proyecto en particular. Y, lamentablemente, todos ellos tienen _muchos_ inconvenientes, que son más profundos que el nivel superficial de la interfaz de usuario...

Dicho esto, abrí un problema de sugerencias sobre Project Manager, dado un poco de tiempo libre, voy a trabajar en algunas mejoras en el área.

He trabajado tanto con Unity como con Godot y encontré que el flujo de trabajo general y la estructura son mucho mejores e intuitivos en Godot (especialmente el modelo de escena en lugar de escena/prefabricado de Unity, el modelo de "guión único" en lugar de los componentes múltiples, la velocidad al descargar/iniciar el motor y exportar y la capacidad de trabajar completamente fuera de línea).

Hay muchos flujos de trabajo y modelos posibles en ambos y nunca es fácil saber cuál es mejor para ti.

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