.NET/C# and scripting in Unity
Unity is a game engine written in C/C++, but in order to make it easier for game developers to develop games, Unity provides C# (pronounced C-sharp) as a scripting programming language to write game logic in Unity. This is because compared with C/C++, C# is easier to learn. In addition, it is a "managed language," which means that it will automatically manage memory for you – allocate release memory, cover memory leaks, and so on.
In this section, we will introduce .NET/C# and scripting in Unity.
.NET profiles in Unity
The Unity game engine uses Mono, an open source ECMA CLI, C#, and .NET implementation, for scripting. You can follow the development of Unity's fork of Mono on GitHub: https://github.com/Unity-Technologies/mono/tree/unity-master-new-unitychanges.
Unity provides different .NET profiles. If you are using the legacy version of Unity, which is before Unity 2018, you may find that it provides two API compatibility levels in the Player settings panel (Edit | Project Settings | Player | Other Settings), which are .NET 2.0 Subset and .NET 2.0. First of all, if you are using a legacy version of Unity, then I strongly recommend that you update your Unity version. Secondly, both the .NET 2.0 Subset and .NET 2.0 profiles in Unity are closely aligned with the .NET 2.0 profile from Microsoft.
If you are using a modern version of Unity, which is Unity 2019 or later, you will find another two .NET profiles supported by Unity, which are .NET Standard 2.0 and .NET 4.x:
Note
The name of the .NET Standard 2.0 profile can be a bit misleading because it is not related to the .NET 2.0 and .NET 2.0 Subset profiles from the legacy versions of Unity.
.NET Standard is a formal specification of the .NET APIs that all .NET platforms have to implement. These .NET platforms include .NET Framework, .NET Core, Xamarin, and Mono. You can find the .NET Standard repository on GitHub: https://github.com/dotnet/standard.
On the other hand, the .NET 4.x profile in Unity matches the .NET 4 series (.NET 4.5, .NET 4.6, .NET 4.7, and so on) of profiles from the .NET Framework.
Therefore, it is a good idea to use the .NET Standard 2.0 profile in Unity, and you should choose the .NET 4.x profile only for compatibility reasons.
Scripting backends in Unity
In addition to the .NET profiles, Unity also provides two different scripting backends, which are Mono and IL2CPP (which stands for Intermediate Language To C++):
You can change the scripting backend of your project in the same settings panel, which can be found by going to Edit | Project Settings | Player | Other Settings.
The key difference between the two scripting backends is how they compile your Unity scripting API code (C# code):
- The Mono scripting backend uses Just-in-Time (JIT) compilation and compiles code on demand at runtime. It will compile your Unity scripting API code to regular .NET DLLs. And, as I mentioned in the previous sections, Unity uses an implementation of the standard Mono runtime for scripting that natively supports C#.
- Alternatively, the IL2CPP scripting backend uses Ahead-of-Time (AOT) compilation and compiles your entire application before it is run. And it not only compiles your Unity scripting API code into .NET DLL but also converts all managed assemblies into standard C++ code. In addition, the runtime of IL2CPP is developed by Unity, which is an alternative to the Mono runtime:
As shown in Figure 1.50, IL2CPP not only compiles C# code into managed assemblies but also further converts assemblies into C++ code, and then compiles the C++ code into the native binary format.
Clearly, IL2CPP takes more time to compile code compared to Mono, so why do we still need IL2CPP?
Well, first, IL2CPP uses AOT compilation, which takes longer to compile, but when you ship the game for a specific platform, the binary files are fully specified, which means that compared to Mono, code generation is greatly improved.
Second, it is worth noting that IL2CPP is the only scripting backend available when building for iOS and WebGL. In addition to iOS and WebGL, Unity has added support for Android 64-bit in Unity 2018.2 to comply with the Google Play Store policy, which requires that starting from August 1, 2019, your apps published on Google Play need to support 64-bit architectures:
And as you can see in the preceding screenshot, the Android 64-bit ARM architecture is not supported on the Mono scripting backend. In this situation, you have to choose the IL2CPP scripting backend.
So, whether we use IL2CPP for better code generation or some specific platforms or architectures, spending more compilation time is still a disadvantage of IL2CPP. So, how should we optimize the compilation time of IL2CPP? I think the following tips will help:
- Don't delete the previous
build
folder, and build your project with the IL2CPP scripting backend at the same location as the folder. This is because we can use incremental building, which means the C++ compiler only recompiles files that have changed since the last build. - Store your project and target build folder on a Solid-State Drive (SSD). This is because when IL2CPP is selected, the compilation process will convert the IL code into C++ and compile it, which involves a lot of read/write operations. A faster storage device will speed up this process.
- Disable anti-malware software before building the project. Of course, this depends on your security strategy.
Well, I hope that by reading this section, you now have a general understanding of Unity's scripting system, such as the .NET profiles in Unity, the two scripting backends, and some optimization tips for IL2CPP.
In the next section, you will learn how to set up your development environment and use the widely used Visual Studio to develop games in Unity.