29 puntos por GN⁺ 2024-04-27 | 13 comentarios | Compartir por WhatsApp
  • Sobre la afirmación de que todos los problemas desaparecen una vez que te acostumbras a Rust
    • Incluso si te acostumbras a Rust, los problemas fundamentales no desaparecen
    • Los juegos son máquinas de estado complejas y, como los requisitos cambian constantemente, no encajan bien con la naturaleza estática y excesivamente restrictiva de Rust
    • El problema de tener que refactorizar el código continuamente es autoinfligido
  • Problemas de refactorización a gran escala causados por el borrow checker
    • Rust obliga a refactorizar con más frecuencia que otros lenguajes
    • En un contexto donde los requisitos del juego cambian seguido, terminas peleando con el borrow checker y necesitando reestructurar el código
    • Es difícil estar de acuerdo con la idea de que la refactorización produce buen código. El buen código surge al iterar ideas y probar cosas
  • La indirección resuelve solo algunos problemas y reduce la productividad de desarrollo
    • Si usas indirección para resolver problemas del borrow checker, la lógica del código se separa y se vuelve más compleja
    • En los juegos se necesitan eventos conectados, timings específicos y mucha gestión de estado, y la indirección dificulta eso
    • En Rust, incluso el código simple debe escribirse de forma verbosa para introducir indirección
  • ECS (Entity-Component-System) resuelve el problema equivocado
    • Las ventajas de ECS son en realidad las ventajas de un generational arena
    • Se analiza ECS desde varias perspectivas: composición dinámica, structure of arrays, solución para el borrow checker de Rust, generational arenas creados dinámicamente, etc.
    • Pero queda la duda de si ECS realmente es el enfoque más adecuado para desarrollar juegos. Más que en rendimiento o composición, habría que enfocarse en la lógica del juego
  • Los sistemas generalizados no llevan a una jugabilidad divertida
    • Si se usan sistemas demasiado generalizados, el resultado es una jugabilidad aburrida
    • Un buen juego requiere diseñar cuidadosamente interacciones detalladas, sincronizar VFX, repetir pruebas de juego y experimentación, y lanzar rápido para recibir feedback
    • Rust prioriza valores que no son adecuados para el prototipado rápido y la iteración
  • Lo importante en el desarrollo de juegos es el prototipado rápido y la iteración, pero los valores de Rust van en dirección opuesta
    • La esencia del desarrollo de juegos es el juego en sí y la experiencia de juego, no el código libre de crashes
    • La mantenibilidad del código de juego no es un valor tan importante en juegos indie. Lo importante es la velocidad de iteración
    • Rust está tan obsesionado con evitar problemas que termina perdiendo de vista lo que realmente importa
  • Los procedural macros están muy por debajo de la reflexión
    • En el desarrollo de juegos hay que escribir código para muchas áreas: código de sistema, gameplay, UI, VFX, audio, herramientas, etc.
    • En Rust, incluso algo tan simple como “imprimir un objeto” requiere escribir código manualmente o crear procedural macros
    • Los procedural macros son mucho más limitados que los macros declarativos y además aumentan bastante el tiempo de compilación
    • La reflexión en C# es muy fácil de usar y permite desarrollar rápido cuando el rendimiento no es crítico
  • El hot reloading juega un papel importante para mejorar la velocidad de iteración
    • El hot reloading es muy útil para UI/dibujo en modo inmediato, debugging y ajuste fino de constantes de gameplay
    • Rust también tiene hot-lib-reloader, pero no es perfecto y requiere planificación y previsión, lo que limita su uso creativo
    • Los desarrolladores de juegos quieren herramientas de más alto nivel que ir más allá de recargar simplemente un struct
  • La abstracción no es opcional, es indispensable
    • Ejemplo real: si se necesita un comportamiento distinto según el estado de la UI, en Rust hace falta refactorizar o abusar de clones
    • Muchas veces no se cambia el código para modificar la lógica de negocio, sino para satisfacer al compilador
    • Rust no tiene un sistema de tipos estructural del estilo “un tipo con estos campos”, así que al refactorizar hay que modificar múltiples partes del código
  • La situación de GUI en Rust es terrible
    • En la UI de juegos, lo importante no es el data binding ni las actualizaciones reactivas, sino poder personalizar la apariencia
    • Lo que la UI de juegos necesita es una GUI bonita, sprites personalizados, animaciones, formas vectoriales, partículas, efectos, flashes, etc.
    • Actualmente no existe una biblioteca de Rust especializada en GUI para juegos
  • La orphan rule debería ser opcional
    • La orphan rule reduce mucho la productividad por razones de seguridad
    • En código de aplicación, no de librería, debería poder desactivarse la orphan rule
  • Los tiempos de compilación han mejorado, pero siguen siendo lentos cuando se usan proc macros
    • Los proc macros como serde aumentan considerablemente el tiempo de compilación
    • Con builds incrementales de 20 a 30 segundos o más, es muy difícil hacer ajustes finos
  • El ecosistema de desarrollo de juegos con Rust parece sobrevendido
    • No hay tanta gente haciendo juegos reales
    • A menudo, proyectos que parecen muy llamativos y reconocidos por su sitio web o README en realidad no lo son tanto
    • Si realmente quieres hacer juegos, recomienda godot-rust. En lugar de obsesionarse con una solución puramente en Rust, conviene apoyarse en un motor maduro
  • La idea de que el estado global es incómodo porque los juegos son single-threaded parte de una razón equivocada
    • En Rust, usar estado global es muy incómodo (static mut, AtomicRefCell, Rc, etc.)
    • Pero, a diferencia de un servicio backend, en los juegos casi todo corre en un solo hilo, así que esa incomodidad no haría tanta falta
    • Considera que fue un error que Bevy introdujera sistemas paralelos. Se hizo por rendimiento, pero obliga al usuario a especificar el orden continuamente y solo agrega más incomodidad
  • El chequeo dinámico de borrow provoca crashes inesperados después de refactorizar
    • Tras usar hecs durante 2 años, vio con frecuencia casos donde queries superpuestos causaban crashes
    • También al usar RefCell, hacer .borrow_mut() desde dos lugares puede causar crashes inesperados
    • Más que mal código, el problema es que Rust obliga a refactorizaciones innecesarias
    • En juegos, RefCell es útil, pero Rust lo vuelve demasiado difícil de usar
  • Falta flexibilidad en los objetos Context
    • Como en Rust es difícil usar estado global, se usa el patrón de pasar un objeto context con referencias agrupadas
    • Pero si solo tomas prestados algunos campos, aparecen errores de compilación por partial borrow
    • Te dicen que dividas el Context y cambies la estructura, pero lo que realmente quieres hacer es la lógica del juego, y cambiar la estructura solo para satisfacer al compilador es una pérdida de tiempo

Ventajas de Rust

  • Cuando compila, normalmente funciona bien. Es especialmente útil para herramientas CLI, procesamiento de datos y escritura de algoritmos
  • Ofrece buen rendimiento sin mucho esfuerzo. Ha tenido la experiencia de que es entre 1.5 y 2.5 veces más rápido que C#
  • Los enum están bien implementados
  • Gracias a Rust analyzer, la experiencia de uso del IDE ha mejorado mucho
  • El sistema de traits está bien logrado. Si la orphan rule se relajara un poco, sería mucho más útil

Opinión de GN⁺

  • Aunque la opinión sobre Rust es en general negativa, parece necesario tomarla en serio porque el autor llegó a esa conclusión después de probar muchas cosas. En particular, tiene sentido su señalamiento de cuán importantes son la practicidad y la velocidad de desarrollo en el dominio del desarrollo de juegos, y de que Rust todavía tiene carencias en esos aspectos.

  • Coincido en que la seguridad que persigue Rust a veces puede reducir gravemente la productividad de desarrollo. Al escribir código Rust, muchas veces se termina gastando más tiempo en satisfacer al compilador que en la lógica misma, y eso parece derivarse de que Rust es, en esencia, un lenguaje especializado en programación de sistemas.

  • Por otro lado, como el desarrollo de juegos suele moverse en entornos single-threaded donde el prototipado rápido y la iteración son importantes, las comprobaciones excesivas de seguridad pueden terminar siendo contraproducentes. He escuchado muchas experiencias de gente que intentó desarrollar juegos con Rust en sus primeros años y terminó frustrada, y parece que esos problemas de fondo todavía no han mejorado demasiado.

  • Por supuesto, motores recientes como Bevy han mejorado la comodidad del desarrollo de juegos con Rust, pero todavía parecen estar muy lejos del nivel de motores maduros como Unity o Godot. Como sugiere este texto, en vez de intentar construir todo puramente con Rust, una alternativa realista puede ser usarlo junto con motores ya existentes.

  • Las ventajas que menciona el autor se sienten mucho más cuando Rust se usa en áreas distintas a los juegos. En campos como la programación de sistemas o el desarrollo de servidores web, la seguridad y el alto rendimiento de Rust son grandes fortalezas, pero en desarrollo de juegos esas ventajas no parecen ofrecer un beneficio tan grande.

  • Al final, Rust no es un lenguaje todoterreno sino uno especializado en ciertos dominios, así que conviene pensar con cuidado si encaja o no con la naturaleza de tu proyecto

13 comentarios

 
coremaker 2024-04-29

Creo que rust es un lenguaje pensado para resolver problemas que surgen por diversos fallos de los desarrolladores, en un contexto donde cada vez hay menos programadores capaces de escribir código íntegro a nivel del núcleo.
No está hecho para desarrollar rápido,
sino para desarrollar con precisión,
así que no es adecuado para proyectos donde aparecen con frecuencia requisitos adicionales de los usuarios y hay que ejecutarlos.

Aun así, creo que el deseo de que aparezca una biblioteca de UI
viene de la expectativa de que su utilidad mejoraría mucho incluso con una UI pequeña y simple funcionando sobre código sólido.

 
kandk 2024-04-29

No he hecho desarrollo de videojuegos, así que no lo sé bien,
pero me parece que o eligieron mal el lenguaje desde el principio (si la iteración de desarrollo era importante, debieron haber elegido un lenguaje de nivel script...),
o que no tenían una comprensión profunda del sistema.
Creo que incluso si hubieran elegido C++, habrían enfrentado problemas parecidos.

 
cosine20 2024-04-29

Así es. Bueno, si hubiera elegido C++, habría existido la opción de Unreal, claro...

 
cosine20 2024-04-29

En estos tiempos, me da la impresión de que lenguajes nativos como Rust o C++ son más adecuados para desarrollar middleware como motores de juego que para desarrollar clientes de juegos.
Tal como casi no hay casos de desarrollo web full stack con lenguajes nativos.

 
kandk 2024-04-29

Es un lenguaje que salió desde el principio para ese propósito, como reemplazo de C++.
Parece que el artículo terminó convirtiéndose en una crítica al lenguaje.

 
cosine20 2024-04-29

Así es. ¿Originalmente había empezado para mejorar el motor interno de Firefox?
El contenido del artículo da la impresión de que intentaron desarrollar en un área que no encaja muy bien con Rust, como si fuera una panacea, y terminaron sufriendo por eso jaja

 
mammal 2024-04-29

Estoy 100% de acuerdo. Para la lógica del juego, un lenguaje con buena productividad parece ajustarse mejor al caso de uso.

 
edunga1 2024-04-28

Como todavía estoy en la etapa de empezar con Rust, empatizo un poco.
Es doloroso tener que modificar demasiado código por cambios en el borrowing.
A diferencia de Python o JavaScript, que tienen muchas expresiones implícitas, Rust tiende a ser explícito, así que a veces termina generando código verboso, y también cansa porque hace que el programador tenga que tomar muchas decisiones.
Aun así, los conceptos que no existen en otros lenguajes se sienten frescos y son divertidos.

Si no hubiera sido por Rust Analyzer o GitHub Copilot, creo que lo habría dejado mucho antes.

 
botplaysdice 2024-04-28

Como era de esperarse, el desarrollo de videojuegos sí que es hardcore...

 
steamb23 2024-04-28

En lugar de programar todo, desde el núcleo hasta el frontend, en Rust,
¿qué tal si el núcleo se escribe en Rust y se combina con un lenguaje de mayor productividad, como Unity u otro motor de juegos?

 
bus710 2024-04-28

Supongo que no se puede evitar, ya que de alguna manera tiende a imponer una estructura muy rígida.

 
[Este comentario fue ocultado.]
 
GN⁺ 2024-04-27
Opinión de Hacker News

Comparte su experiencia desarrollando un cliente de metaverso y señala los problemas de Rust

  • Casi no hay casos de desarrollo de juegos 3D a gran escala con Rust
  • Refactorizar y conectar las distintas partes del programa es doloroso
  • El renderizado es casi adecuado, pero el stack no está completo ni es confiable
  • Los sistemas GUI 2D son débiles y requieren demasiado código por cada cuadro de diálogo
  • Coincide en que el sistema async se extiende incluso a áreas donde no es necesario

Como desarrollador de juegos con 20 años de experiencia, considera que Rust no es adecuado para el desarrollo de juegos

  • El código de gameplay debe ser flexible y tener muchos casos límite para crear juegos interesantes
  • El tiempo de compilación importa y los cambios estructurales son frecuentes
  • ECS es útil para algunos sistemas, pero es difícil de usar en código de gameplay o de UI

El ecosistema de desarrollo de juegos en Rust depende del hype

  • Intentó desarrollar juegos con Rust, pero la experiencia fue terrible de inmediato
  • Tiempos de compilación lentos, descargas enormes de paquetes y la dificultad propia de Rust
  • Aunque se dice que otras herramientas no son tan seguras como Rust, la seguridad de memoria casi nunca fue un problema importante en los juegos

Compara la experiencia de desarrollo de juegos con Bevy y Unity, entre otros

  • Hoy en día es difícil entender por qué alguien elegiría Rust para desarrollar juegos
  • Meter todo a la fuerza en ECS dificulta crear un gameplay divertido
  • Considerando el rendimiento de las PC modernas, no hace falta preocuparse en exceso por la optimización multihilo

El lenguaje Nim podría ser más adecuado que Rust para el desarrollo de juegos

  • No estorba al desarrollador y soporta hot reloading

Rust parece un lenguaje dogmático que obliga a programar de una forma específica

  • Prioriza la seguridad de memoria por encima de todo, pero en el desarrollo de juegos eso no resulta tan útil
  • El lenguaje ideal para desarrollar juegos debería ser productivo, tener un rendimiento adecuado y estar pensado para programadores experimentados dispuestos a asumir riesgos

La demo de tooling de Allen Blomquist muestra que el ciclo de retroalimentación del desarrollo es importante

  • Volvió a Unity porque Rust no podía ofrecer el entorno de trabajo que quería

El problema fundamental de Rust es que abandona la orientación a objetos y favorece la programación funcional

  • Puede ayudar en el núcleo de más bajo nivel, pero no es adecuado en niveles superiores

En desarrollo de juegos, Rust es la peor elección

  • Los valores de Rust, que persiguen exactitud, seguridad y código perfecto, no encajan con el desarrollo de juegos
  • Los juegos tienen una vida útil corta y ciclos de desarrollo breves, por lo que la calidad del código no es tan importante
  • Puede ser útil para desarrollar motores de juego, pero debería usarse junto con un lenguaje de scripting muy flexible

Al programar en D, se dio cuenta de que cambiar el layout de datos es mucho más fácil que en C

  • Cambiar entre tipos por referencia y tipos por valor es difícil en C, pero fácil en D