14 Punkte von GN⁺ 2025-12-30 | 13 Kommentare | Auf WhatsApp teilen
  • Die von Unity verwendete Mono-Laufzeit zeigt im Vergleich zu modernem .NET eine deutlich geringere Ausführungsgeschwindigkeit; beim selben C#-Code wurden Unterschiede von bis zu 15x beobachtet
  • In realem Spielecode wurde 100 Sekunden für die Unity-Ausführung auf Mono-Basis gemessen, während derselbe Code unter .NET 38 Sekunden benötigte, was sich stark auf die Effizienz von Debugging und Tests auswirkt
  • Selbst im Release-Modus bleibt der Unterschied bestehen: Mono benötigt 30 Sekunden, .NET 12 Sekunden, also mehr als 2,5x selbst in einer optimierten Umgebung
  • Ursachen sind unter anderem ineffiziente JIT-Kompilierung und fehlgeschlagenes Inlining in Mono sowie übermäßige Speicherkopien, im Gegensatz zu den modernen CoreCLR-JIT-Optimierungen von .NET
  • Sobald Unity die .NET-Modernisierung auf CoreCLR-Basis abschließt, sind sowohl in Spielen als auch im Editor große Leistungssteigerungen möglich; das dürfte auf eine Beseitigung einer versteckten Performance-Steuer für alle Unity-Projekte hinauslaufen

Hintergrund zur Nutzung von Mono in Unity

  • Unity verwendet seit 2006 das Mono-Framework zur Ausführung von C#-Code
    • Damals war Mono die einzige plattformübergreifende .NET-Implementierung und als Open Source von Unity anpassbar
  • Ab 2014 stellte Microsoft .NET Core als Open Source bereit und veröffentlichte 2016 .NET Core 1.0
    • Danach entwickelte sich das .NET-Ökosystem mit Roslyn-Compiler, neuem JIT und Performance-Verbesserungen rasant weiter
  • 2018 erklärten Unity-Ingenieure, dass sie an einem CoreCLR-Port arbeiteten, mit erwarteten 2- bis 10-fachen Performance-Gewinnen gegenüber Mono
  • Doch selbst Ende 2025 ist spielseitige Ausführung auf CoreCLR-Basis weiterhin nicht möglich

Performance-Lücke zwischen Mono und .NET

  • Der Simulationscode eines Unity-Projekts wurde außerhalb von Unity direkt unter .NET ausgeführt und verglichen
    • Unity/Mono-Umgebung: 100 Sekunden, .NET-Umgebung: 38 Sekunden (im Debug-Modus)
  • Im Release-Modus bleibt der Unterschied mit 30 Sekunden für Mono und 12 Sekunden für .NET bestehen
    • .NET zeigt zudem starke Multithreading-Optimierung, etwa bei der Generierung einer 4K×4K-Karte in unter 3 Sekunden
  • Hauptursache ist die ineffiziente Codegenerierung von Mono; selbst in einfachen Schleifen treten 15-fache Geschwindigkeitsunterschiede auf

Assembly-Vergleich: Mono vs. .NET

  • Vergleich der erzeugten x64-Assemblies mit identischem Testcode
    • Der .NET-JIT verschiebt schleifeninvariante Ausdrücke aus der Schleife heraus (Hoisting) und arbeitet nur mit einem Minimum an Registeroperationen
    • Mono wiederholt Speicherkopien mit Dutzenden von mov-Befehlen und verliert durch ineffizientes Inlining zusätzlich an Leistung
  • Laufzeit einer Schleife mit int.MaxValue Wiederholungen
    • .NET: 750ms, Mono: 11.500ms, Unity Editor (Debug): 67.000ms
  • Mono wiederholt innerhalb der Schleife unnötige Speicherbewegungen und Vergleichsoperationen

Bedeutung der CoreCLR-Einführung

  • CoreCLR bietet moderne Funktionen wie aktuellen JIT, Span<T>-API, SIMD-Optimierungen und Unterstützung für Hardware-Instruktionen
    • Diese Funktionen eröffnen Potenzial für zusätzliche Performance-Gewinne von mehr als 2x
  • Unitys Burst-Compiler erzeugt zwar auf LLVM-Basis nativen Code, bringt aber Einschränkungen bei C#-Features mit sich
    • Der moderne JIT von CoreCLR kann Burst-ähnliche Performance liefern und hat dabei weniger Sprachbeschränkungen
  • CoreCLR unterstützt AOT (Ahead-of-Time-Kompilierung), was schnellere Startzeiten und Unterstützung für Plattformen mit JIT-Einschränkungen (z. B. iOS) ermöglichen kann
    • Unity erklärt jedoch weiterhin, an IL2CPP festhalten zu wollen

Fazit: Unity braucht eine Modernisierung von .NET

  • Mono zeigt gegenüber modernem .NET eine 1,5- bis über 3-fach langsamere Ausführungsleistung und wirkt damit als versteckter Kostenfaktor für alle Unity-Projekte
  • Erwartete Effekte bei einer CoreCLR-Einführung
    • Bessere Laufzeitleistung, schnellere iterative Builds, verbesserte GC, Wegfall von Domain Reloads, größerer Anteil an Managed Code
  • Die Roadmap von Unity 6.x enthält zwar .NET Modernization, diese ist aber erst nach 2026 geplant
  • Wenn die CoreCLR-Unterstützung fertig ist, könnte sie sowohl Unity-Entwicklern als auch Spielern eine spürbare Leistungsrevolution bringen
  • Aktuell bleiben die Grenzen von Mono ein Performance-Flaschenhals für das gesamte Unity-Ökosystem

13 Kommentare

 
dunward 2026-01-05

Es ist schön, mal wieder einen Artikel über Unity zu sehen.
Ich habe ihn mit großem Interesse gelesen.

 
quack337 2025-12-31

Ah … Offenbar basiert Mono immer noch auf dem Legacy-.NET-Framework …
Es ist zwar kein Spiel, aber ich migriere gerade eine etwa 100.000 Zeilen große Finanzanwendung auf Basis von .NET 4.8 + LINQ to SQL + WinForms nach .NET 10 + Entity Framework, und ich merke deutlich, dass sie viel schneller geworden ist. Rechenaufgaben, die früher 10 Sekunden dauerten, sind teilweise auf 3 Sekunden gesunken!

 
mhcoma 2025-12-30

Falls dies erfolgreich eingeführt wird, dürfte sich die Optimierung der unzähligen Indie-Games vermutlich verbessern ...

 
intajon 2025-12-30

Es wäre schön, wenn auch NuGet-Kompatibilität hinzugefügt würde (oder liegt das daran, dass ich mich mit Unity nicht gut auskenne?)

 
sonohoshi 2025-12-31

Es wird zwar nicht offiziell unterstützt, aber es gibt ein Open-Source-Projekt namens NuGetForUnity.

 
rkttu 2025-12-30

Theoretisch sollten auf .NET Standard 2.0 ausgerichtete NuGet-Pakete auch in einer Unity-Umgebung geladen und verwendet werden können … aber offenbar gibt es dabei doch einige Unannehmlichkeiten.

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

 
rkttu 2025-12-30

Ein weiterer Grund, warum Mono unbedingt mit CoreCLR modernisiert werden muss, ist meiner Meinung nach, dass Unity weder besonders die Möglichkeiten noch den Willen haben dürfte, in Performance-Verbesserungen für Mono zu investieren. Ich denke, es ist richtig, die Altlasten aus der Zeit des .NET Frameworks so schnell wie möglich aufzuräumen. :-D

 
rkttu 2025-12-30

Und ich fände es gut, wenn auch berücksichtigt würde, dass ab .NET 10 das Problem, das sie früher mit IL2CPP lösen wollten, zwar in eine andere Richtung entwickelt, aber dennoch präzise adressiert wird (Native AOT).

Natürlich bleibt die Einschränkung, dass dabei kein zwischendurch bearbeitbarer C++-Code erzeugt wird, aber letztlich hat sich die Erzeugung nativer Binärdateien ohne Just-in-Time von .NET 8 ausgehend bis .NET 10 weiter deutlich ausgereift.

Deshalb halte ich es für keine gute Entscheidung von Unity, die Modernisierung hin zu CoreCLR weiter aufzuschieben. Oder vielleicht wäre sogar ein vollständiger Wechsel zu einer ganz anderen Sprache oder Grundlage die sinnvollere Option!

 
sonohoshi 2025-12-30

Unity hat weder die Mittel noch den großen Willen, in die Performance von Mono zu investieren.

Dem stimme ich ebenfalls voll und ganz zu...

 
sonohoshi 2025-12-30

Stimmt schon, aber ich verstehe nicht so recht, warum man unbedingt die Editor-Performance vergleichen muss ... Man hätte zumindest einen Debug-Build zum Vergleich heranziehen können, oder? Oder auch nicht — hätte das die Aussagekraft am Ende noch weiter geschwächt? Andererseits wirken sowohl IL2CPP als auch Mono gleichermaßen wie veraltete Technologien.

 
foriequal0 2025-12-30

Bei großen Projekten beeinträchtigt die Editor-Performance die Developer Experience erheblich, daher ist auch die Editor-Performance wichtig. Das Starten des Editors ist langsam, der Asset-Import ist langsam, und auch die Schleife aus Debugging/Tests ist langsam ...

 
sonohoshi 2025-12-30

Ah ... natürlich ist auch das wichtig. Als ich den Text zum ersten Mal gelesen habe, wirkte es auf mich so, als hätte der Autor eher über die grundlegendere Ausführungsgeschwindigkeit des Codes sprechen wollen. Dass Unity, wie du sagst, auch beim Editor langsam ist, der Import langsam ist und die gesamte Testschleife insgesamt langsam ist, stimmt natürlich ebenfalls ...

 
GN⁺ 2025-12-30
Hacker-News-Kommentare
  • Als professioneller Spieleentwickler beteilige ich mich normalerweise nicht an Unity-Diskussionen, aber dieses Thema berührt direkt mein Fachgebiet, daher lasse ich einen Kommentar da.
    Im Artikel gab es ein paar Stellen, die so wirkten, als hätte ihn jemand mit wenig Unity-Entwicklungserfahrung geschrieben.
    1. Die Trennung von Simulation und Darstellungsschicht ist seit langem eine gängige Methode zur Performance-Optimierung (früher meist in C++ umgesetzt).
    2. Die meisten Spiele werden mit IL2CPP ausgeliefert, nicht mit dem Mono-Backend.
    3. In aktuellem Unity ist es für Performance üblich, Burst Compiler und HPC# zu nutzen. Das Job System hilft enorm.
    4. Im Editor zu profilieren ist fast bedeutungslos, weil er viel langsamer ist als selbst ein Debug-Build.
      Kurz gesagt: Unity-Entwickler freuen sich bei diesem Update weniger auf Performance-Gewinne als auf den Zugang zu modernen Sprachfeatures. Und es ist üblich, GC zur Laufzeit zu minimieren oder mit nicht verwaltetem Speicher und DOTS daran vorbeizuarbeiten.
    • Du scheinst dich zu sehr von Unitys Marketing beeinflussen zu lassen. Unity geht solche Dinge immer an, indem es problematische Systeme schrittweise etwas verbessert.
      IL2CPP ist letztlich nur ein Codegenerator geringer Qualität, der .NET-IL nach C++ übersetzt und sich auf optimierende Compiler verlässt.
      Das sieht man auch in Unitys Blog über die internen Strukturen von IL2CPP.
      Burst/HPC# folgt ebenfalls Trends wie ECS oder SoA, bleibt in der Performance aber hinter gut geschriebenem C++ oder CoreCLR-C# zurück.
      Außerdem sind diese Technologien geschlossen und Unity-spezifisch, man kann sie außerhalb davon nicht nutzen. Unity vermarktet sie immer mit Benchmarks gegen das langsame Mono.
      Am Ende blieb Unity nichts anderes übrig, als CoreCLR zu akzeptieren, und dann wird man feststellen, dass normales C# schneller ist als der bisherige komplexe Code.
    • Danke für den Kommentar, sagt der Autor. Unser Spiel ist strukturell überhaupt nicht von Unity-Typen oder DLLs abhängig, daher unterscheidet es sich von einem typischen Unity-Spiel.
      Wir verwenden IL2CPP nicht, weil es mit Dingen wie dynamischem DLL-Laden zur Laufzeit, Reflection und Struct-Packing mit FieldOffset nicht kompatibel ist.
      Modder können Funktionen per IL-Injection erweitern, was die Entwicklung am Ende beschleunigt.
      Burst und HPC# bevorzuge ich wegen ihrer Komplexität und Einschränkungen nicht. Gerade der Performance-Unterschied zwischen Mono und .NET ist frustrierend.
      Auch Editor-Profiling war nützlich, weil es Leistungsverbesserungen in ähnlichen Verhältnissen wie der echte Build zeigte. Statt des ungenauen Standard-Profilers von Unity nutze ich allerdings ein selbst gebautes Tracing-System.
      GC bleibt weiterhin ein Problem. String-Verarbeitung und UI erzeugen in jedem Frame Garbage. Mit CoreCLR bekäme man bessere APIs und einen bewegenden GC, was Probleme mit Speicherfragmentierung reduzieren könnte.
  • Unity ist leicht zugänglich, hat aber wegen seiner monolithischen Struktur starke technische Schulden.
    Der Asset Store ist großartig, aber die Engine selbst wirkt unausgereift.
    Das Mono-basierte Scripting ist strukturell kompliziert auf CoreCLR zu migrieren.
    Wenn Unity den Core wirklich verbessern will, müsste es wie Blender 3.x den gesamten Editor neu designen.
    Im Moment fühlt es sich wie eine UI von 1999 an.
    • Das größte Problem von Unity ist, dass neue Features nicht fertiggestellt, sondern aufgegeben werden.
      Unzählige Plugins und Tools bleiben im Stadium „0.x-preview“ stehen und funktionieren 5 bis 10 Jahre später entweder nicht mehr oder gehen zwischen neueren Assets unter.
      Deshalb nutze ich inzwischen nur noch Versionen ab 1.0. Sonst hängt man an verlassenen Plugins und muss am Ende doch alles erneut portieren.
      Das ist schlecht für Unity, für Entwickler und für Nutzer.
    • Unity wirkt wie ein Unternehmen ohne klare Richtung.
      Intern fehlt durch gescheiterte eigene Spieleentwicklung das Gespür für echte Spieleproduktion.
      Es werden einfach angeforderte Features ergänzt, aber es gibt keine konsistente Vision.
    • WebGPU ist eine Abstraktionsschicht wie Vulkan.
      Wenn Performance entscheidend ist, sollte man Vulkan direkt aufrufen, und wenn Portabilität wichtig ist, WebGPU verwenden.
      Da die Implementierungen je nach Browser unterschiedlich sind, entsteht Overhead, aber das ließe sich lösen, wenn WebGPU auf OS-/Treiber-Ebene bereitgestellt würde.
    • Bei Unity hat man immer das Gefühl, für alles erst einen Workaround finden zu müssen.
      Godot dagegen bietet einfache und sinnvolle Bausteine, mit denen man frei bauen kann, was man möchte.
    • Unity bricht die APIs seiner eigenen Features so oft, dass selbst Tutorials nicht mehr funktionieren.
      Im Asset Store ist es ähnlich: Wegen Versionskompatibilitätsproblemen ist Wartung schwierig, und die meisten werden zu vernachlässigten Assets.
      Wenn Unity nützliche Assets aufkauft, werden sie weder ordentlich integriert noch bleiben konkurrierende Assets bestehen.
      Unreal Engine bietet solche Funktionen dagegen eher auf Engine-integriertem Niveau.
  • Unitys GC verwendet Boehm GC und ist dadurch viel langsamer als .NET oder Mono.
    Es gibt auch keine Pläne von Unity, für IL2CPP einen besseren GC einzuführen.
    Wenn ein CoreCLR-basierter Editor kommt, könnte der Editor sogar schneller sein als ein Build.
    Zugehörige Diskussion: Unity CoreCLR und .NET-Modernisierung
    • Ein besserer GC ist schön, aber in Spielen ist es wichtiger, Allokationen pro Frame bei 0 zu halten.
      Wenn inkrementeller GC gut funktioniert, sind auch Stotterprobleme nicht so groß.
    • Mit dem Wechsel auf CoreCLR wird die Abschaffung von Domain Reloads den Editor stark beschleunigen.
    • Mono hat bereits einen präzisen GC, daher frage ich mich, warum Boehm verwendet wird.
  • Seit Unity 2018 die Portierung auf CoreCLR diskutiert hat, ist es ein langer Weg gewesen.
    Da C# an sich inzwischen sehr schnell geworden ist, muss Unity diese Umstellung unbedingt mit voller Kraft priorisieren.
    Unser Team brauchte ein paar Monate, um von .NET Framework 4.7.2 auf .NET 6 zu wechseln, und spätere Upgrades auf LTS-Versionen waren dann in wenigen Stunden erledigt.
  • Unity scheint nicht mehr die technische Kompetenz zu haben, eine Migration zu CoreCLR umzusetzen.
    Es gibt ständig Verzögerungen, und Führungskräfte gehen.
    Als Alternative empfehle ich die .NET-10-basierte Stride-Engine. Dort gibt es keinen Boundary-Overhead wie bei Unity.
    • Der Fortschritt ist langsam, aber Unity treibt die Umstellung auf CoreCLR tatsächlich voran.
    • Stride bietet nur einen Teil der Funktionen von Unity.
      Godot ist Open Source, aber die C#-Unterstützung ist instabil, und wenn Web-Builds nicht funktionieren, ist es für Game Jams ungeeignet.
      Man braucht eine echte Sandbox-Lösung mit GPU-Unterstützung.
    • Das Problem ist nicht mangelnde Technikkompetenz, sondern Ressourcen- und Führungsprobleme.
      Prioritäten ändern sich ständig, Anforderungen werden angepasst, und dadurch wird Arbeit immer wiederholt.
      Die Entwickler sind nach wie vor hervorragend, aber es fehlt an konsequenter Durchsetzung.
    • Unity trägt die Last, die vielen übernommenen Technologien und Add-ons entweder einzustellen oder zu integrieren.
      Solche groß angelegten Rewrites sind auch aus Sicht eines CEO eine Entscheidung mit hohem Risiko.
  • Ich habe am Circuits-System von Rec Room gearbeitet und dabei erlebt, wie man Unity-Abhängigkeiten entfernt und alles unter CoreCLR testbar macht.
    Das Ergebnis war eine deutliche Performance-Steigerung, und durch die geringere Engine-Abhängigkeit wurde auch die Wartung des Codes einfacher.
    Indem wir Unity-Konzepte nur dort exponierten, wo es nötig war, und die Grenzen per Tests erzwangen, haben wir den Wert dieser logischen Trennung klar gespürt.
  • Ich frage mich, warum der Autor Mono statt IL2CPP benutzt. IL2CPP ist viel schneller, daher sind Mono-Builds veraltet. Wenn Performance wichtig ist, sollte IL2CPP der erste Schritt sein.
  • Mein Traum ist es, das .NET SDK direkt auf einem Android-Handy zu installieren und nativ auszuführen.
    Mit Root-Zugriff und in Kombination mit Netzwerktopologien wie WireGuard oder Tailscale wäre das auch als tragbarer Server perfekt.
    Mit dem neuen GC in .NET 10 würden auch Ruckler in Spielen fast verschwinden.
    Derzeit streame ich Spiele mit Sunlight + Moonlight vom Haupt-PC und spiele sie auf dem Handy.
    Dank des OLED-Displays mit hoher Bildwiederholrate hält sich auch der Batterieverbrauch in Grenzen.
    • Die Root-Beschränkung gibt es aus Sicherheitsgründen. Sie soll Infektionen über USB-Ports in der Öffentlichkeit erschweren und deshalb das Rooten schwieriger machen.
    • Mit MAUI (Xamarin) kann man etwas Ähnliches machen.
      Es ist zwar nicht das .NET SDK, aber die Mono-Laufzeit ist in die App eingebettet, sodass es sich praktisch ähnlich anfühlt.
  • Ich frage mich, warum Unity immer noch nicht vollständig auf .NET umsteigt.
    Der Cross-Platform-Vorteil von Mono ist ohnehin verschwunden, daher verstehe ich nicht, warum man komplizierte Hacks wie IL2CPP weiter pflegt.
    • Die Sunk-Cost-Falle ist groß. Es wurde bereits massiv in Mono, IL2CPP, Burst usw. investiert, daher ist ein Richtungswechsel schwer.
    • Unity hat Mono stark angepasst, daher lässt es sich nicht einfach austauschen.
      Über Jahre haben sich nicht standardisierte Änderungen angesammelt, und außer einem Großunternehmen könnte das kaum jemand neu optimieren.
  • Es überrascht mich, dass Unity den Wechsel auf CoreCLR schon 2018 begonnen hat und ihn bis heute nicht abgeschlossen hat.
    Für ein Projekt dieser Größenordnung hätte ich gedacht, ein bis zwei Jahre müssten ausreichen.