14 puntos por GN⁺ 2025-12-30 | 13 comentarios | Compartir por WhatsApp
  • El runtime Mono que usa Unity muestra una velocidad de ejecución notablemente inferior frente a .NET moderno, con casos donde el mismo código en C# presenta una diferencia de hasta 15 veces
  • En código real de juegos, la ejecución de Unity basada en Mono tardó 100 segundos, mientras que el mismo código en .NET tardó 38 segundos, lo que también afecta mucho la eficiencia de depuración y pruebas
  • Incluso en modo Release, Mono tardó 30 segundos y .NET 12 segundos, por lo que la diferencia de rendimiento de más de 2.5 veces se mantiene aun en entornos optimizados
  • La causa está en la compilación JIT ineficiente de Mono y sus fallas de inlining, además de copias de memoria excesivas, en contraste con las optimizaciones modernas del JIT CoreCLR de .NET
  • Si Unity completa su modernización de .NET basada en CoreCLR, podría lograr una gran mejora de rendimiento tanto en los juegos como en el editor, eliminando así un impuesto oculto de rendimiento en todos los proyectos de Unity

Antecedentes del uso de Mono en Unity

  • Unity usa el framework Mono para ejecutar código en C# desde 2006
    • En ese momento, Mono era la única implementación multiplataforma de .NET y, al ser de código abierto, Unity podía modificarlo
  • Desde 2014, Microsoft publicó .NET Core como código abierto y en 2016 lanzó .NET Core 1.0
    • Desde entonces, el ecosistema .NET ha avanzado rápidamente con el compilador Roslyn, un nuevo JIT y múltiples mejoras de rendimiento
  • En 2018, ingenieros de Unity dijeron que estaban trabajando en el port de CoreCLR y esperaban una mejora de rendimiento de 2 a 10 veces frente a Mono
  • Sin embargo, hasta finales de 2025 sigue siendo imposible ejecutar juegos sobre CoreCLR

Brecha de rendimiento entre Mono y .NET

  • Se comparó directamente ejecutando en .NET, fuera de Unity, el código de simulación de un proyecto de Unity
    • Entorno Unity/Mono: 100 segundos, entorno .NET: 38 segundos (en modo Debug)
  • En modo Release, la diferencia se mantiene: Mono 30 segundos y .NET 12 segundos
    • .NET destaca por su optimización multihilo, por ejemplo al generar un mapa de 4K×4K en menos de 3 segundos
  • La causa principal es la generación ineficiente de código en Mono, con diferencias de 15 veces incluso en bucles simples

Comparación de ensamblado: Mono vs .NET

  • Comparando el ensamblado x64 generado a partir del mismo código de prueba
    • El JIT de .NET mueve invariantes del bucle fuera del bucle (hoisting) y realiza solo la mínima cantidad de operaciones en registros
    • Mono repite copias de memoria con decenas de instrucciones mov y su inlining ineficiente degrada el rendimiento
  • Tiempo de ejecución del bucle repetido con int.MaxValue
    • .NET: 750ms, Mono: 11,500ms, Unity Editor (Debug): 67,000ms
  • Mono repite movimientos de memoria y comparaciones innecesarias dentro del bucle

Qué significa adoptar CoreCLR

  • CoreCLR ofrece funciones modernas como JIT actualizado, API Span<T>, optimizaciones SIMD y soporte para instrucciones de hardware
    • Estas capacidades podrían aportar una mejora adicional de más de 2 veces en rendimiento
  • El compilador Burst de Unity genera código nativo basado en LLVM, pero tiene limitaciones en las funciones de C#
    • El JIT moderno de CoreCLR puede ofrecer un rendimiento similar al de Burst con menos restricciones del lenguaje
  • CoreCLR también soporta AOT (compilación anticipada), lo que puede mejorar la velocidad de arranque y permitir compatibilidad con plataformas que limitan JIT, como iOS
    • Aun así, Unity mantiene su postura de seguir conservando IL2CPP

Conclusión: Unity necesita modernizar .NET

  • Mono muestra un rendimiento de ejecución entre 1.5 y 3 veces o más lento que el .NET moderno, lo que funciona como un costo oculto en todos los proyectos de Unity
  • Efectos esperados al adoptar CoreCLR
    • Mejor rendimiento en runtime, iteraciones de compilación más rápidas, mejoras en GC, eliminación del domain reload, mayor proporción de código administrado
  • La hoja de ruta de Unity 6.x incluye .NET Modernization, pero está prevista para después de 2026
  • Cuando el soporte de CoreCLR esté completo, podría aportar una verdadera transformación de rendimiento tanto para desarrolladores de Unity como para jugadores
  • Por ahora, las limitaciones de Mono siguen siendo un cuello de botella de rendimiento para todo el ecosistema de Unity

13 comentarios

 
quack337 2025-12-31

Ah... parece que Mono sigue basado en el legacy .NET Framework...
No es un juego, pero estoy migrando una app financiera de WinForm de unas 100 mil líneas, con .NET 4.8 + LINQ to SQL, a .NET 10 + Entity Framework, y se siente claramente mucho más rápida. ¡Incluso hay tareas de cálculo que pasaron de tardar 10 segundos a 3!

 
intajon 2025-12-30

Ojalá también agregaran compatibilidad con NuGet (¿será porque no conozco bien Unity?)

 
sonohoshi 2025-12-31

No tiene soporte oficial, pero existe un proyecto de código abierto llamado NuGetForUnity.

 
rkttu 2025-12-30

En teoría, los paquetes de NuGet dirigidos a .NET Standard 2.0 deberían poder cargarse y usarse también en el entorno de Unity... pero parece que, de todos modos, hay bastantes puntos incómodos.

https://learn.microsoft.com/ko-kr/dotnet/…

 
sonohoshi 2025-12-30

Es cierto, pero no entiendo muy bien por qué comparan específicamente el rendimiento del editor... Aunque sea, ¿no podrían haber traído una comparación con una build de depuración? ¿O no? ¿Entonces eso habría sido todavía menos convincente? Por otro lado, da la impresión de que tanto IL2CPP como Mono son tecnologías igual de anticuadas.

 
foriequal0 2025-12-30

En proyectos grandes, el rendimiento del editor también importa porque puede deteriorar mucho la experiencia de desarrollo. La apertura del editor es lenta, la importación de assets también es lenta, y el ciclo de depuración/pruebas también es lento...

 
sonohoshi 2025-12-30

Ah... sí, claro que esto también es importante. Cuando lo leí por primera vez, me pareció que el autor quería hablar de un problema más fundamental relacionado con la velocidad de ejecución del código. También es cierto que, como dices, Unity tiene un editor lento, importaciones lentas y, en general, un ciclo de pruebas lento...

 
dunward 2026-01-05

Qué gusto ver una publicación relacionada con Unity.
La leí con mucho interés.

 
mhcoma 2025-12-30

Si se implementa con éxito, probablemente mejorará la optimización de muchísimos juegos indie...

 
rkttu 2025-12-30

Otra razón por la que Mono definitivamente debe modernizarse hacia CoreCLR, creo, es que Unity probablemente no tiene ni las condiciones ni la voluntad de invertir mucho en mejorar el rendimiento de Mono. Creo que lo correcto es dejar atrás cuanto antes el legado de la era de .NET Framework. :-D

 
rkttu 2025-12-30

Y también me parece que sería bueno considerar que, a partir de .NET 10, el problema que antes intentaban resolver con IL2CPP está siendo abordado con precisión, aunque en una dirección distinta de desarrollo, mediante Native AOT.

Claro, la limitación es que en el proceso no se genera código C++ editable en el medio, pero al final la producción de binarios nativos sin que ocurra Just-In-Time ha ido madurando desde .NET 8 y llegó aún más consolidada en .NET 10.

Por esa razón, creo que seguir postergando la modernización hacia CoreCLR no va a ser una buena decisión para Unity. O quizá reemplazarlo por completo y pasarse a otro lenguaje o a otra base podría ser una alternativa más válida.

 
sonohoshi 2025-12-30

> Es probable que Unity no tenga ni las condiciones ni mucha voluntad de invertir en mejorar el rendimiento de Mono.

También estoy totalmente de acuerdo con esto...

 
GN⁺ 2025-12-30
Comentarios de Hacker News
  • Como desarrollador profesional de videojuegos, normalmente no participo en discusiones sobre Unity, pero este tema toca directamente mi área de especialidad, así que dejo mi opinión.
    Hubo varias partes del texto que parecían escritas por alguien con poca experiencia desarrollando en Unity.
    1. Separar la simulación y la capa de presentación ha sido desde hace mucho una forma común de optimizar el rendimiento (antes se implementaba sobre todo en C++).
    2. La mayoría de los juegos se publican con IL2CPP, no con el backend Mono.
    3. En las versiones modernas de Unity es normal usar Burst Compiler y HPC# para mejorar el rendimiento. El Job System ayuda mucho.
    4. Perfilar en el editor casi no tiene sentido, porque es mucho más lento que un build de depuración.
      En resumen, la razón por la que los desarrolladores de Unity esperan esta actualización no es tanto por el rendimiento sino por el acceso a funciones modernas del lenguaje. Y también es común minimizar el GC durante la ejecución o evitarlo usando memoria no administrada y DOTS.
    • Creo que te dejaste llevar demasiado por el marketing de Unity. Unity siempre ha avanzado mejorando de a poco sistemas problemáticos.
      IL2CPP no es más que un generador de código de baja calidad que convierte .NET IL a C++, y depende de compiladores optimizadores.
      Se puede ver en la explicación interna de IL2CPP en el blog de Unity.
      Burst/HPC# también sigue tendencias como ECS o SoA, pero rinde peor que C++ bien escrito o que C# sobre CoreCLR.
      Además, estas tecnologías son cerradas y exclusivas de Unity, así que no se pueden usar fuera de ahí. Unity siempre hace marketing con benchmarks comparándolas con Mono lento.
      Al final Unity no tendrá más remedio que adoptar CoreCLR, y cuando eso pase se darán cuenta de la realidad: que el C# normal puede ser más rápido que todo ese código complejo que ya tienen.
    • Gracias por la opinión; soy el autor del texto. Nuestro juego tiene una arquitectura que no depende en absoluto de tipos de Unity ni de DLL de Unity, así que es distinto de un juego típico hecho en Unity.
      No usamos IL2CPP porque no es compatible con carga dinámica de DLL en tiempo de ejecución, reflection ni empaquetado de structs con FieldOffset.
      Los modders pueden ampliar funcionalidades con inyección de IL, y eso al final acelera el desarrollo.
      No me gustan Burst ni HPC# porque traen mucha complejidad y restricciones. La diferencia de rendimiento entre Mono y .NET lo hace todavía más frustrante.
      El perfilado en el editor también fue útil porque mostraba mejoras de rendimiento en proporciones similares al build real. En cambio, el profiler por defecto de Unity era impreciso, así que usamos un sistema de trazas hecho por nosotros.
      El GC sigue siendo un problema. El manejo de strings y la UI generan basura en cada frame. Con CoreCLR tendríamos APIs mejores y un GC con movimiento, lo que ayudaría a reducir la fragmentación de memoria.
  • Unity es fácil para empezar, pero su estructura monolítica le ha generado una gran deuda técnica.
    El Asset Store es excelente, pero el motor en sí se siente poco pulido.
    La base de scripting sobre Mono es estructuralmente compleja de migrar a CoreCLR.
    Si Unity de verdad quiere mejorar su núcleo, tendría que rediseñar todo el editor, como hizo Blender 3.x.
    Ahora mismo se siente como una UI de 1999.
    • El mayor problema de Unity es que deja abandonadas funciones nuevas sin terminarlas.
      Montones de plugins y herramientas se quedan en fase “0.x-preview”, y 5 o 10 años después ya no funcionan o quedan enterrados bajo assets nuevos.
      Por eso ahora solo uso cosas con versión 1.0 o superior. Si no, terminas dependiendo de plugins abandonados y tarde o temprano tienes que portear todo otra vez.
      Todos pierden: Unity, los desarrolladores y los usuarios.
    • Unity parece una empresa que perdió el rumbo.
      Internamente le falta sensibilidad real para hacer juegos por sus fracasos en desarrollo de juegos propios.
      Solo agregan funciones que les piden, pero no tienen una visión coherente.
    • WebGPU es una capa de abstracción como Vulkan.
      Si el rendimiento importa, es mejor llamar Vulkan directamente, y si importa la portabilidad, entonces hay que usar WebGPU.
      Como la implementación cambia entre navegadores, aparece sobrecarga, pero eso podría resolverse si el sistema operativo ofreciera WebGPU a nivel de driver.
    • Con Unity siempre se siente que para lograr algo tienes que buscar alguna forma de rodearlo.
      En cambio, Godot te da bloques de construcción simples y con sentido para crear libremente lo que quieras.
    • Unity rompe seguido las APIs de sus propias funciones, al punto de que hasta los tutoriales dejan de funcionar.
      En el Asset Store pasa lo mismo: por problemas de compatibilidad entre versiones, mantener cosas se vuelve difícil y la mayoría termina siendo assets abandonados.
      Cuando Unity compra assets útiles, ni siquiera los integra bien, y los competidores desaparecen.
      En cambio, Unreal Engine ofrece estas funciones como parte integrada del motor.
  • El GC de Unity usa Boehm GC, así que es mucho más lento que el de .NET o Mono.
    Unity tampoco parece tener planes de meter un GC mejor en IL2CPP.
    Cuando salga un editor basado en CoreCLR, incluso el editor podría ser más rápido que el build.
    Debate relacionado: CoreCLR y modernización de .NET en Unity
    • Está bien que el GC mejore, pero en juegos lo más importante es mantener las asignaciones por frame en 0.
      Si el GC incremental funciona bien, el stutter tampoco debería ser un gran problema.
    • Al migrar a CoreCLR, eliminar la recarga de dominios mejorará muchísimo la velocidad del editor.
    • Mono ya tiene un GC preciso, así que no se entiende por qué usan Boehm.
  • Ha sido un camino largo desde que Unity habló de portar CoreCLR en 2018.
    Como C# se volvió muy rápido por sí mismo, Unity tiene que poner todos sus recursos en esta transición.
    A nuestro equipo le tomó unos meses pasar de .NET Framework 4.7.2 a .NET 6, y después las actualizaciones entre versiones LTS fueron cuestión de horas.
  • Da la impresión de que Unity ya no tiene la capacidad técnica para completar la migración a CoreCLR.
    Todo sigue retrasándose y los líderes se van.
    Como alternativa recomiendo Stride, basado en .NET 10, que no tiene el mismo overhead de frontera que Unity.
    • El avance es lento, pero Unity sí está impulsando la transición a CoreCLR.
    • Stride solo ofrece una parte de las funciones de Unity.
      Godot es open source, pero su soporte para C# es inestable, y si no puedes hacer builds web, no sirve bien para game jams.
      Hace falta una solución sandbox real con soporte de GPU.
    • No es falta de capacidad técnica, sino un problema de recursos y liderazgo.
      Las prioridades cambian todo el tiempo y los requisitos se modifican, así que el trabajo se repite.
      Los desarrolladores siguen siendo muy buenos, pero falta impulso constante.
    • Unity tiene la carga de descartar o integrar muchísimas tecnologías y addons que compró.
      Un rewrite de esta magnitud también es, desde la perspectiva de un CEO, una decisión muy riesgosa.
  • Desarrollé el sistema Circuits de Rec Room, y tuve la experiencia de quitar dependencias de Unity para poder probarlo en CoreCLR.
    El resultado fue una mejora importante de rendimiento, y al reducir la dependencia del motor también se volvió más fácil mantener el código.
    Al exponer conceptos de Unity solo donde hacía falta y reforzar los límites con tests, confirmé el valor de una separación lógica.
  • Me pregunto por qué el autor usa Mono en vez de IL2CPP. IL2CPP es mucho más rápido, así que un build con Mono ya es algo anticuado. Si el rendimiento importa, IL2CPP debería ser el primer paso.
  • Mi sueño es instalar directamente el SDK de .NET en un teléfono Android y ejecutarlo de forma nativa.
    Con acceso root y combinado con herramientas de red como WireGuard o Tailscale, sería perfecto también como servidor portátil.
    Con el nuevo GC de .NET 10, el stutter en juegos casi desaparecería.
    Por ahora juego en el teléfono haciendo streaming desde mi PC principal con Sunlight + Moonlight.
    Gracias a la pantalla OLED de alta tasa de refresco, el consumo de batería también es bajo.
    • Las restricciones de root existen por razones de seguridad. Se busca dificultar el rooteo para evitar infecciones por puertos USB en lugares públicos.
    • Se puede hacer algo parecido con MAUI (Xamarin).
      No es el SDK de .NET, pero como el runtime de Mono va incluido en la app, en la práctica se siente parecido.
  • Me pregunto por qué Unity todavía no hace la transición completa a .NET.
    Si las ventajas multiplataforma de Mono ya desaparecieron, no se entiende por qué siguen manteniendo hacks complejos como IL2CPP.
    • Aquí pesa mucho la trampa del costo hundido. Ya invirtieron muchísimo en Mono, IL2CPP, Burst y demás, así que cambiar de rumbo es difícil.
    • Unity personalizó Mono profundamente, así que no pueden reemplazarlo así nomás.
      Se fueron acumulando años de modificaciones no estándar, y salvo que seas una empresa enorme, no es fácil volver a optimizar todo desde cero.
  • Sorprende que Unity comenzara la transición a CoreCLR en 2018 y todavía no la haya terminado.
    Uno pensaría que un proyecto así debería tomar solo 1 o 2 años.