Thanks for the update.
Seems I need to update my Bayesian priors. I don’t believe that I will be using CoreCLR in Unity 7000.0. Hopefully CoreCLR can be a stable complete replacement for Mono in the Unity 8000.0 timeframe.
Agreed.
Thanks for the update.
Seems I need to update my Bayesian priors. I don’t believe that I will be using CoreCLR in Unity 7000.0. Hopefully CoreCLR can be a stable complete replacement for Mono in the Unity 8000.0 timeframe.
Agreed.
It actually would be useful to know what the plan is in detail, and to expand on the actual technical and practical factors that led to this choice, because you what you said about this “new strategy” feels extremely confusing…
If I understand right what you said, the new plan is to delay having access to the .NET 8+ BCL and instead to implement the usual .Net standard 2.1 franken-mono BCL so it can run on the CoreCLR JIT/runtime (and GC ?) ???
How is putting together an even more frankenstein old-Mono-BCL-running-on-CoreCLR not a huge amount of extra work delaying the whole endeavor ?
Under that new frankenstein BCL/runtime, will we still get incremental code reload ? The CoreCLR GC ? CoreCLR hardware intrinsics ? What would be the actual value of that weird hybrid for end users ?
What are the actual roadblocks to getting the .NET 8 BCL in time for Unity 7 ? Migrating the various packages codebases ? Migrating/adapting the IL2CPP and Burst compilers ?
Won’t those gradual (but still breaking) changes make the transition even more painful for store asset devs ?
How is that not a “high level” decision driven by the fear of releasing a backward compatibility breaking Unity 7 version ? Why a solution involving extending a bit the Unity 6 lifecycle in parallel hasn’t been chosen ?
Edit : Now that I think of it, maybe it’s the other way around ? A .Net standard 2.1 compliant “stripped” .NET 8 BCL ? Doesn’t the mono BCL have a tons of extra public APIs not defined in the .Net Standard that still can be used in Unity ? Won’t projects using them break horribly ?
No, we’d be running with the .NET 8 BCL, but we would only offer NETStandard21 as a profile for code compilation in the initial releases. So the only APIs you’d “see” from your code would be the same NETStandard21 surface that you see in most projects today.
I know it’s limiting, but it allows us to focus on issues around Mono/CoreCLR parity before tackling issues arising from new .NET 8 features, as well as avoiding laying a trap where people use .NET 8 APIs in the Editor before discovering they’re not available in the Player. Again, this is just what we expect to deliver initially, and opening up the full .NET 8 profile would then come afterwards - it’ll be a temporary limitation to allow us to get Editor builds out sooner.
Because we’d only be restricting the API surface for user code, it doesn’t prevent us from leveraging CoreCLR features on the engine side - so yes you’d still have the new GC, we could still implement incremental code reload, etc.
I’ve just noticed this on the release notes for Unity 6000.2.0, what does it mean? Is it an important milestone Unity has achieved?
IL2CPP: Updated
il2cpp.exeandUnityLinker.exeto target .NET 8.
These are separate command-line utilities that do not run inside Unity. They’ve been updated to target .NET 8 (I think they were on .NET 7 previously?), but it’s unrelated to the larger task of updating Unity itself.
Unity has 2 or 3 systems for everything:
All of that is maintained, and all of that takes development time. All of that needs to be ported to .Net core. Also, 3rd party plugins sometimes don’t work in our projects because they use a different system.
At some point, Unity should consider trimming the fat. There is just way to much tech debt accumulated by trying to maintain backwards compatibility.
Giving up HDRP and BIRP may be more worth a thought.
But from all others, only Legacy anim and IMGUI could be removed without massive loss. Not sure about UPM, never used it.
Everything else is necessary because they do their role well Unity is forced to have it (Il2cpp)…
You use UPM to install burst, ECS, Input system, cinemachine, unity ai, etc… Practically all unity packages are distributed using UPM. For a list of all UPM packages you are using, you can take a look at Packages/manifest.json
Oh huh, that’s actually different from what mechanism imports the data of an asset bought from the store? Mean both is triggered done via the package manager.
EDIT: Right, not every bought and imported asset lands in the manifest.
Guess one could replace the other then, but probably maintenance/conversion to .NET isn’t a huge thing for this.

Git dependency for UPM was already neglected. I am not so sure if UPM have any changed for years
I doubt that. They clearly has data indicates enough usage currently to justify support effort. Otherwise they will just announce a deprecation plan, like Unity Cloth.
I myself also depend on IMGUI for many editor extensions where it makes sense and is lightweight enough compared to UITK.
Yeah nah. 90% of inspectors are still IMGUI based.
And plenty of plugins still use, among the most popular being Odin Inspector.
Not a big fan of having both Mono and CoreCLR. I’d prefer breaking changes in Unity 7, but there’s probably reason for this. It might be something, which is not fully compatible with CoreCLR.
Runtime
I’d expect runtime code to work without any issues. Maybe there are some third party plugins, which rely on current GC, because they access managed memory in unmanaged code (see Porting Unity to CoreCLR).
There might be also some collectible assembly restrictions, which are causing issues (PInvoke, Marshalling delegates and TLS, see Collectible assemblies for dynamic type generation - .NET | Microsoft Learn)
Editor
For Editor code, I expect A LOT of breaking changes coming from need for cooperative “domain reloads”. It might be so big that it would essentially mean that only empty projects would work properly on Unity 7. But it’s still not enough reason for two runtimes. In case of “cooperation issues” Unity could just dump the whole runtime and start it over (as done with Mono now).
Technical details
Unity plans to use AssembyLoadContext and collectible assemblies for user code.
To make reload work, all references to user code must be cleared.
This means there are no references to instances of user types and no references to user types.
So all user-defined components, scriptable objects and assets are destroyed. All unity events are unsubscribed. All static variables, which contain reference to user types are cleared. All type caches containing user types are cleared.
Unity will handle components, scriptable objects and assets by itself. The type caches likely as well. Events and static variables will probably need some cooperation. @xoofx written somewhere that there will be a detailed information about stuff, which is blocking unload (like in memory profiler - list of GC roots and “path” towards user types). Not sure if this is still applies.
I’d expect something like [OnBeforeDomainReload] as callback for user to unregister from events and static fields. Other alternative might be using weak events.
Question
What are the sources of issues with CoreCLR that we still need Mono for compatibility?
I think anything you share about your progress, roadblocks and current work is greatly appreciated by the community. We loved the blog posts by @xoofx and @JoshPeterson. I understand you can’t share ETAs and community is okay with that. I expect there will be a period of silence just before the release - so you can “load and fire the PR ammo”.
Fingers crossed for Unite Barcelona (November) ![]()
I agree that Runtime code is not so likely to be impacted by the swap of the scripting runtime itself, but the issues that could arise will tend to be more subtle.
For example, one difference is that CoreCLR’s handling of floating point math is guaranteed to be IEEE754 compliant, while Mono is not, meaning that it is possible you’ll get slightly different results from floating-point computations between the two. Now, hopefully in most situations it doesn’t matter if your numbers change by a couple of ULPs, but there may be situations where it’s enough to be an issue, especially considering that these types of things can compound over multiple frames.
Actually, that’s one part that we encourage everybody to address before CoreCLR is available:
If you make your stuff work with “Do not reload Domain or Scene” - a.k.a. ‘fast enter playmode’, a feature which has been available for a while now - then not only do you get a nice improvement on entering Play mode, you also do most of the work of making your code support ‘co-operative reload.’
We’re looking at how we can better enable people to turn this on for their projects, both through providing some helpers to make it as easy as possible to implement the co-operative reload, and through things like getting all of our first-party packages and top third-party Asset Store packages to support it.
Cooperative domain reload is also not something we have to ship at the same time as the CoreCLR runtime itself: we could effectively emulate the current domain reload by shoving everything into a single massive ALC and then always reloading that. Of course that’s not how we want things to work eventually, but it’s another example of how we can decouple the work.
Yes, we call this ‘ALC leak detection’. I believe the plan is still to ship the tooling we’ve developed around this to help you diagnose why your code is being kept alive.
Something like that, yep.
So, as noted - there are some specific behaviour changes between Mono and CoreCLR that we know about: floating point behaviour changes; different performance characteristics when moving between managed and native code; changes in static initialisation order; more strict enforcement of accessibility constraints; more overflow checks; etc.
Then, add to that the behaviour changes that we don’t know about - particularly those caused by e.g. differences in how the Mono BCL is implemented compared to the CoreCLR BCL.
Many of these changes come from CoreCLR being more defined or more ‘correct’ than Mono, so in the long run they’re good changes to have (and we don’t generally want to, like, “Mono-ify” them for the sake of compatibility), but in the short run they could still be enough to cause subtle issues. One of the big advantages of having the Mono and CoreCLR editors in parallel is that if you do see something strange under CoreCLR, you’ll be able to open up your project in the Mono editor instead and check whether you’re seeing the same issue or not, without other aspects of the Editor changing at the same time.
Don’t some current Unity packages not work properly when domain reload is disabled with enter play mode settings? Addressables and the Input System are the two that come to mind.
Mind you, I think we’re all guilty of writing static systems to depend on domain reload to reset quickly. Though I imagine a lot of these can be fixed by hooking into EditorApplication.onPlayModeStateChanged.
Both of those are working fine in my projects. There certainly was teething issues, but for my uses everything has been resolved ages ago.
I agree with the others. The legacy IMGUI is probably one of those things that will never go away as it’s far more than just an UI system. It’s THE lowlevel API for drawing and processing events. Even UGUI uses the Event type for event processing and that type is the heart of IMGUI. It can be used for so much more than just UI. I actually made simulation projects in the past that had only a single MonoBehaviour script and the only callbacks used were Awake, Start and OnGUI :). Some time ago I’ve written an IMGUI crash course if you want to know some of the bits and pieces about it. One example I made completely in IMGUI is my FixedUpdate simulation to visually explain how FixedUpdate works. It’s also 100% IMGUI. It doesn’t even use FixedUpdate
(ps: the little windows are draggable, just don’t zoom out completely as WebGL has a memory limit).
Do you have any examples of these? The overflow check thing will probably be a big boon (especially if it’s configurable to throw on overflows in editor/debug builds but skip checks in release builds), but stricter accessibility constraints is something that could be worrying.
Static initialization order is something that we shouldn’t be relying on, but of course it’s very easy to end up doing it be misstake, but those bugs are often not that hard to work around.

still it will take a while, maybe in 7, i assume
IIRC the accessibility thing is that under CoreCLR, private/internal modifiers are enforced at runtime, while in Mono they’re only enforced at compile time. So if you have some precompiled assembly which is calling code that used to be public but has since changed to be non-public, under Mono it continues to work just fine, but under CoreCLR it will break.
And yes, none of these issues are necessarily difficult to deal with - as you say it’s “often not that hard to work around” - but only after you’ve found them.