- 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
serdeaumentan considerablemente el tiempo de compilación - Con builds incrementales de 20 a 30 segundos o más, es muy difícil hacer ajustes finos
- Los proc macros como
- 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
- En Rust, usar estado global es muy incómodo (
- El chequeo dinámico de borrow provoca crashes inesperados después de refactorizar
- Tras usar
hecsdurante 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,
RefCelles útil, pero Rust lo vuelve demasiado difícil de usar
- Tras 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
enumestá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
Creo que
rustes 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.
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.
Así es. Bueno, si hubiera elegido C++, habría existido la opción de Unreal, claro...
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.
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.
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
Estoy 100% de acuerdo. Para la lógica del juego, un lenguaje con buena productividad parece ajustarse mejor al caso de uso.
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.
Como era de esperarse, el desarrollo de videojuegos sí que es hardcore...
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?
Supongo que no se puede evitar, ya que de alguna manera tiende a imponer una estructura muy rígida.
Opinión de Hacker News
Comparte su experiencia desarrollando un cliente de metaverso y señala los problemas de Rust
Como desarrollador de juegos con 20 años de experiencia, considera que Rust no es adecuado para el desarrollo de juegos
El ecosistema de desarrollo de juegos en Rust depende del hype
Compara la experiencia de desarrollo de juegos con Bevy y Unity, entre otros
El lenguaje Nim podría ser más adecuado que Rust para el desarrollo de juegos
Rust parece un lenguaje dogmático que obliga a programar de una forma específica
La demo de tooling de Allen Blomquist muestra que el ciclo de retroalimentación del desarrollo es importante
El problema fundamental de Rust es que abandona la orientación a objetos y favorece la programación funcional
En desarrollo de juegos, Rust es la peor elección
Al programar en D, se dio cuenta de que cambiar el layout de datos es mucho más fácil que en C