Deprecation of support for the .Net Scripting backend used by the Universal Windows Platform

As of Unity 2018.1, we have been supporting two scripting backends on the Universal Windows Platform (UWP): .NET, and IL2CPP. With the release of 2018.2, we are deprecating support for the .NET scripting backend. The goals for this deprecation are twofold.

The first goal of this deprecation is to make it easier for you to port games to UWP. Much of the developer pain associated with porting games to UWP in the past has been due to differences in API surface area and differences between the .NET Native and the Mono and IL2CPP runtimes Unity uses on other platforms. This change will ultimately make it easier to port games to UWP going forward for most developers.

The second reason for this deprecation is to make it easier for us to support you by fixing issues efficiently. Because the .NET scripting backend is completely different than the runtimes we use for all other Unity platforms, it has been challenging for us to maintain a consistent quality-level relative to the rest of Unity. This deprecation will ultimately enable us to spend less time maintaining the .NET scripting backend, and more time working on the features and issues that are most important to you.

IL2CPP has the same .NET API surface as all other Unity platforms, and IL2CPP has had support for accessing WinRT types and APIs for some time now. So with the addition of the IL2CPP managed debugger in 2018.2, the developer experience on IL2CPP is now on a par with and superior to what the .NET scripting backend provides.

IL2CPP has already been the default since 2017.2, , so we expect most will have no issues with this. However, if you have not yet tried using IL2CPP and you do experience any issues, please be sure to file them. We plan for full removal of .NET scripting backend support in 2019.1.

Feel free to ask questions and discuss it in this thread.

Do you have instructions on how to use the managed debugger for IL2CPP? We are trying to use it with a UWP HoloLens build that was previously .NET and we are having trouble figuring out where the source files are and how to debug it.

We’re working on documentation for this. But in the meantime, I made a short video showing how to do it:

https://oc.unity3d.com/index.php/s/rx7KD0SYeQXr6qn

Thank you!

I tried replicating what you do in the video but it seems to refuse to connect.My cursor spins for a second and then nothing.

I’m trying to build and run on a Hololens.

Basically echoing what Charlie said, when attempting to attach the debugger to the running build in the other Visual Studio window, the cursor simply spins for a few seconds and then never successfully attaches. There is no error provided, and the output window is blank so it isn’t clear why it isn’t attaching.

Also as discussed in other forum posts, there seems to be a significant slowdown in iterations building with IL2CPP vs. .NET. I’ve tried following Unity - Manual: IL2CPP Overview and “Scripts Only Build” but as someone developing for the HoloLens for the past 2 years, I can say I don’t think we would have been able to complete our projects on schedule with the significantly increased iteration time. It seems to take us about 10 minutes to go from build to HoloLens deployment, whereas before it was about 3 minutes. Also as you were debugging on the HoloLens, the Unity C# projects feature that allowed us to modify the code in that built project, which saved a tremendous amount of time and helped us debug and tweak our HoloLens apps quickly and efficiently. The new IL2CPP doesn’t seem to support this, which I think is a major loss of iteration development that improved effeciency for HoloLens Development.

That adds up in daily development. My feedback would be that you really should consider maintaining .NET support unless you guys can figure out how to increase the build & deploy times and increase iteration time. We are upgrading now because of the deprecation but, begrudgingly :-/ at this point.

2 Likes

We’re looking at the connection issues with debugging - it was brought up to our attention yesterday. Strangely, it only seems to happen on HoloLens and not other UWP devices. Stay tuned - we’ll definitely fix it.

As for iteration times: is 10 minutes an incremental build time, or a clean build time? I would fully expect it to take 10 minutes to build for the first time, however, subsequent builds should be much, much faster. If they’re not, I’d like to follow up to figure out what’s going on there. One more thing to check is whether you’re using .NET 4.x or .NET Standard 2.0 API compatibility level - the latter is smaller and should build much quicker.

Lastly, iteration times is our number one focus post 2018.3. We’re working on making IL2CPP emit less code, and on making our class libraries smaller.

2 Likes

Thanks for the update. Can you possibly let us know when you have the HoloLens fix? Do you suspect it will be weeks/months? Would it be a 2018.2 patch? Thanks.

In regards to the project details and timings:

It is for an incremental build. We are using .NET 4x in the project. I tested by adding a new TestScript.cs to one of my game objects and made a build. Here are the timings:

Build from Unity to VS-> 2:12 seconds
Compilation Time from VS → 2:57 seconds
Linker Time → 77 seconds

Deploy time to HoloLens was another few minutes (I didn’t have a chance to time it). Some of the deployment lag may be due to symbols, which I’ve since disabled, but it was still several minutes for deployment.

I am using an Alienware 15 R2 and the project and Unity are on my SSD.

I first need to figure out what’s failing. I aim to do it today if I can get my hands on a device. Hopefully it can be worked around without changes to the engine. But if we do end up having to fix it there, we’ll definitely put it in 2018.2 patch.

I assume you disabled your antivirus software as pointed out in that doc page? Windows Defender on my machine causes the builds to take 3 times longer…

How many files got recompiled in that 2:57? Adding one script shouldn’t result more than a few files being recompiled if you built on top of a previous build. I’d expect the compilation time to take at most 15 seconds.

Also, can we get a bug report on the link times? I suspect we might be hitting an edge case somewhere. A repro project would help us evaluate that kind of things and potentially make it faster. If you do report a bug, please link to this post where I ask for it.

Let’s work together on this and make it faster!

Thanks for the swift responses and help. I did disable the anti-virus software.

I’ve been able to get the compile times down. Release I am at 110 seconds and Debug is curiously faster at 45 seconds. Still slower than the expected 15 seconds. Linker is still slow. I’m attaching the build log here.

1>------ Build started: Project: Il2CppOutputProject, Configuration: Release Win32 ------
1>Building GameAssembly.dll with MsvcWinRtToolChain
1>    Msvc Install Version: 15.0
1>    Msvc Install SDK Directory: C:\Program Files (x86)\Windows Kits\10
1>    Msvc Linker Path: C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.14.26428\bin\HostX64\x86\link.exe
1>    Msvc Compiler Path: C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.14.26428\bin\HostX64\x86\cl.exe
1>
1>    Output directory: C:\Users\shaddad\Documents\DI Work\Projects\AR IRAD\AR-IRAD\AR Project\Builds\Project IL2CPP\build\bin\Win32\Release
1>    Cache directory: C:\Users\shaddad\Documents\DI Work\Projects\AR IRAD\AR-IRAD\AR Project\Builds\Project IL2CPP\build\obj\il2cppOutputProject\Win32\Release
1>Il2CppGenericMethodDefinitions.cpp
1>Il2CppMethodPointerTable.cpp
1>Il2CppSequencePointTable9.cpp
1>Il2CppSequencePointTable11.cpp
1>Il2CppSequencePointTable10.cpp
1>Il2CppSequencePointTable12.cpp
1>Il2CppSequencePointTable14.cpp
1>Il2CppSequencePointIndexTable.cpp
1>Il2CppSequencePointTable8.cpp
1>Il2CppSequencePointTable15.cpp
1>Il2CppSequencePointTable13.cpp
1>Il2CppMethodHeaderInfoTable.cpp
1>Il2CppAttributes.cpp
1>Il2CppMethodExecutionInfoIndexTable.cpp
1>Bulk_Generics_69.cpp
1>GenericMethods2.cpp
1>GenericMethods5.cpp
1>Bulk_Generics_13.cpp
1>GenericMethods1.cpp
1>GenericMethods8.cpp
1>GenericMethods10.cpp
1>Bulk_Generics_80.cpp
1>GenericMethods6.cpp
1>Bulk_Generics_14.cpp
1>Bulk_Generics_5.cpp
1>Bulk_Generics_34.cpp
1>GenericMethods0.cpp
1>Bulk_Generics_16.cpp
1>Il2CppMethodExecutionInfoTable7.cpp
1>GenericMethods9.cpp
1>Bulk_Generics_6.cpp
1>Bulk_Generics_70.cpp
1>Bulk_Generics_4.cpp
1>GenericMethods4.cpp
1>Bulk_Generics_7.cpp
1>Il2CppMethodExecutionInfoTable5.cpp
1>Il2CppMethodExecutionInfoTable6.cpp
1>GenericMethods3.cpp
1>Bulk_Generics_43.cpp
1>Bulk_Generics_3.cpp
1>Bulk_Generics_15.cpp
1>Il2CppMetadataUsage.cpp
1>GenericMethods7.cpp
1>Bulk_Generics_58.cpp
1>Bulk_Assembly-CSharp_17.cpp
1>Bulk_Generics_17.cpp
1>Bulk_Generics_81.cpp
1>Bulk_Generics_35.cpp
1>Bulk_Generics_2.cpp
1>Bulk_Generics_0.cpp
1>Bulk_Generics_71.cpp
1>Bulk_Generics_45.cpp
1>Bulk_Generics_56.cpp
1>Bulk_Generics_73.cpp
1>Bulk_Generics_61.cpp
1>Bulk_Generics_44.cpp
1>Bulk_Generics_1.cpp
1>Bulk_Generics_72.cpp
1>Bulk_Generics_57.cpp
1>Bulk_Generics_64.cpp
1>Bulk_Generics_60.cpp
1>Bulk_Generics_46.cpp
1>Bulk_Generics_12.cpp
1>Bulk_Generics_47.cpp
1>Bulk_Generics_82.cpp
1>Bulk_Generics_79.cpp
1>Bulk_Generics_59.cpp
1>Bulk_Generics_85.cpp
1>Bulk_Generics_52.cpp
1>Bulk_Generics_83.cpp
1>Bulk_Generics_75.cpp
1>Bulk_Generics_74.cpp
1>Bulk_Generics_32.cpp
1>Bulk_Generics_51.cpp
1>Bulk_Generics_24.cpp
1>Bulk_Generics_63.cpp
1>Bulk_Generics_53.cpp
1>Bulk_Generics_55.cpp
1>Bulk_Generics_54.cpp
1>Bulk_Generics_68.cpp
1>Bulk_Generics_41.cpp
1>Bulk_Generics_27.cpp
1>Bulk_Generics_84.cpp
1>Bulk_Generics_76.cpp
1>Bulk_Generics_77.cpp
1>Bulk_Generics_39.cpp
1>Bulk_Generics_67.cpp
1>Bulk_Generics_40.cpp
1>Bulk_Generics_48.cpp
1>Bulk_Generics_65.cpp
1>Il2CppMethodExecutionInfoTable8.cpp
1>Bulk_Generics_25.cpp
1>Bulk_Generics_28.cpp
1>Bulk_Generics_49.cpp
1>Bulk_Generics_62.cpp
1>Bulk_Generics_31.cpp
1>Bulk_Generics_22.cpp
1>Bulk_Generics_8.cpp
1>Bulk_Generics_78.cpp
1>Bulk_Generics_18.cpp
1>Bulk_Generics_23.cpp
1>Bulk_Generics_29.cpp
1>Bulk_Generics_66.cpp
1>Bulk_Generics_33.cpp
1>Bulk_Generics_50.cpp
1>Bulk_Generics_30.cpp
1>Bulk_Generics_26.cpp
1>Bulk_Generics_20.cpp
1>Bulk_Generics_19.cpp
1>Bulk_Generics_21.cpp
1>Bulk_Generics_36.cpp
1>Bulk_Generics_11.cpp
1>Bulk_Generics_37.cpp
1>Bulk_Generics_38.cpp
1>Bulk_Generics_42.cpp
1>Il2CppMethodExecutionInfoTable9.cpp
1>Il2CppMethodScopeTable.cpp
1>Il2CppSequencePointTable16.cpp
1>Bulk_Generics_9.cpp
1>Bulk_Generics_10.cpp
1>GenericMethods11.cpp
1>Il2CppCodeRegistration.cpp
1>Il2CppDebuggerMetadataRegistration.cpp
1>Il2CppMetadataRegistration.cpp
1>ObjectFiles: 952 of which compiled: 124
1>    Time Compile: 31360 milliseconds Il2CppMetadataUsage.cpp
1>    Time Compile: 10510 milliseconds Bulk_Assembly-CSharp_17.cpp
1>    Time Compile: 9484 milliseconds Bulk_Generics_31.cpp
1>    Time Compile: 9442 milliseconds Bulk_Generics_30.cpp
1>    Time Compile: 9437 milliseconds Bulk_Generics_29.cpp
1>    Time Compile: 9302 milliseconds Bulk_Generics_56.cpp
1>    Time Compile: 9153 milliseconds Bulk_Generics_6.cpp
1>    Time Compile: 8894 milliseconds Bulk_Generics_25.cpp
1>    Time Compile: 8775 milliseconds Bulk_Generics_26.cpp
1>    Time Compile: 8707 milliseconds Bulk_Generics_28.cpp
1>Total compilation time: 101932 milliseconds.
1>Creating library C:\Users\shaddad\Documents\DI Work\Projects\AR IRAD\AR-IRAD\AR Project\Builds\Project IL2CPP\build\obj\il2cppOutputProject\Win32\Release\linkresult_769EFA2F168828C59D6B92D09A0D1364\GameAssembly.lib and object C:\Users\shaddad\Documents\DI Work\Projects\AR IRAD\AR-IRAD\AR Project\Builds\Project IL2CPP\build\obj\il2cppOutputProject\Win32\Release\linkresult_769EFA2F168828C59D6B92D09A0D1364\GameAssembly.exp
1>LINK : /LTCG specified but no code generation required; remove /LTCG from the link command line to improve linker performance
1>Total link time: 71926 milliseconds.
1>Encoding map file using command: C:\Users\shaddad\Documents\DI Work\Projects\AR IRAD\AR-IRAD\AR Project\Builds\Project IL2CPP\Il2CppOutputProject\IL2CPP\MapFileParser\MapFileParser.exe -format=MSVC "C:\Users\shaddad\Documents\DI Work\Projects\AR IRAD\AR-IRAD\AR Project\Builds\Project IL2CPP\build\bin\Win32\Release\GameAssembly.map" "C:\Users\shaddad\Documents\DI Work\Projects\AR IRAD\AR-IRAD\AR Project\Builds\Project IL2CPP\build\bin\Win32\Release\SymbolMap"
1>Cleaned up 249 object files.
2>------ Build started: Project: Project, Configuration: Release Win32 ------
2>App.cpp
2>UnityGenerated.cpp
2>c:\users\shaddad\documents\di work\projects\ar irad\ar-irad\ar Project\builds\Project il2cpp\Project\app.cpp(26): warning C4973: 'Windows::UI::ViewManagement::IApplicationView2::SuppressSystemOverlays::set': marked as deprecated
2>c:\users\shaddad\documents\di work\projects\ar irad\ar-irad\ar Project\builds\Project il2cpp\Project\app.cpp(26): note: Message: 'Use the TryEnterFullScreen method and IsFullScreenMode property instead of SuppressSystemOverlays. For more info, see MSDN.'
2>Generating code
2>0 of 160 functions ( 0.0%) were compiled, the rest were copied from previous compilation.
2>  0 functions were new in current compilation
2>  0 functions had inline decision re-evaluated but remain unchanged
2>Finished generating code
2>Project.vcxproj -> C:\Users\shaddad\Documents\DI Work\Projects\AR IRAD\AR-IRAD\AR Project\Builds\Project IL2CPP\build\bin\Win32\Release\Project.exe
2>GENERATEPROJECTPRIFILE : warning PRI249: 0xdef00520 - Invalid qualifier: DLL-RESOURCES
2>GENERATEPROJECTPRIFILE : warning PRI249: 0xdef00520 - Invalid qualifier: DLL-RESOURCES
2>GENERATEPROJECTPRIFILE : warning PRI249: 0xdef00520 - Invalid qualifier: DLL-RESOURCES
2>C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\VisualStudio\v15.0\AppxPackage\Microsoft.AppXPackage.Targets(2428,5): warning APPX0108: The certificate specified has expired. For more information about renewing certificates, see http://go.microsoft.com/fwlink/?LinkID=241478.
2>Done building project "Project.vcxproj".
========== Build: 2 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

I could open a bug if you’d like but I cannot upload source code w/out permission, which likely would involve an NDA. Let me know if I should still open a bug report as well anyways.

It’s not much we can do without source, as these incremental compilation times really depends on your code.

We have improvements to linking times coming already. As you noticed, building debug is faster because the compiler doesn’t spend time optimizing your code.

+10 on this. In my experience with Unity development, being able to iterate on the C# external to the project without needing a full Unity build cycle is incredibly valuable.

The usual maximum productivity developer loop for Unity is just playing a scene inside the editor – editing C# and building/running inside the editor is very quick for PC apps, thanks to the Mono runtime. There’s no IL2CPP build cycle required inside the editor, and no switching to VS2017 to play your scene.

This doesn’t work for UWP apps. My app uses UWP audio APIs that are inaccessible when running inside the editor.

Previously, I would just build the C# projects for my app, then do my UWP-specific edit/compile/run cycle inside of VS2017. No switching back to Unity required to iterate on my code.

But with this deprecation, now every change I make to Unity C# code that’s run by UWP forces a full Unity project build and a VS2017 project rebuild. I have to use both tools for every code change.

I certainly appreciate that you are going to work hard on shortening this loop. However, there is only so much you can do, given that both Unity and VS2017 are now involved whereas previously it was only VS2017.

Are you also planning to deprecate the Mono runtime for Unity PC apps? If not, then is it conceivable that you could support the Mono runtime for UWP apps? The most productive possible outcome for UWP development would seem to be the same support for UWP apps that already exists for PC apps – namely, the ability to make C# code changes and immediately play your scene in the editor, with full access to UWP APIs. (Essentially, providing the ability to run the Unity editor itself under UWP.) Is there any roadmap towards this goal?

(HoloLens-specific question: alternatively, is it possible to use HoloLens remoting to support playing Unity HoloLens apps directly from the editor to a HoloLens?)

In the meantime, I will probably factor my app in such a way that I can run it under Unity without the UWP functionality to optimize iterating on the Unity scripts, while moving as much C# as possible into separate DLLs that I can iterate on in VS2017 without IL2CPP rebuilds. That step is just fundamentally painful, given how far from C# source IL2CPP output is.

Thanks for your engagement with the community – as problematic as this change is, it’s good to see UWP getting focus from Unity.

Edit: I see elsewhere you had this useful advice:

Thanks for providing the technical background on why the feature was more fragile than it appeared. I definitely hope you are able to reach the point of changing as few IL2CPP output files as possible when making incremental changes to C# scripts, as that’ll certainly accelerate this loop.

2 Likes

Amen. This a very stupid idea that will have a huge impact on developer productivity.

I agree that being able to export from unity with the C# projects is a huge help.

I am in the ID@XBOX program and the documentation for integrating Xbox live functionality into my game had me export the unity project into Visual studio then add in extra C# Xbox live projects so I could then use the various api calls.

There are C++ versions of these projects but I don’t know C++. As such it would be a huge undertaking to get the xbox live stuff in if I could not export using the .net scripting back end.

(I’m on vacation - my replies to all posts will be delayed)

It’s not unfeasible, but we didn’t have any immediate plans of this. The biggest problem of Mono on UWP is that Mono currently does not support calling into COM and Windows Runtime APIs. That means all the C# code that calls into UWP specific APIs wouldn’t work on Mono. It took me 14 months of work to add this support into IL2CPP, so it’s definitely not something we can make happen quickly.

You can use those APIs from your scripts in Unity in C# with IL2CPP. You don’t have to use C++.

Could you explain a little more how I would go about this? Would I simply add the external C# projects to the C# project while its still within unity? or add the external C# projects to the C++ project once the build from unity is complete?

Just following up, do you have any updates on getting managed IL2CPP debugging working with the HoloLens?

Managed debugging with IL2CPP and the Holoens does work in Unity 2018.2, but it is a bit slow, likely do to slower Wifi connections. We’re working on improving that right now though.