Posted On: 2021-03-29
The Unity game engine is not written in C#. This may be old hat for some readers, but, when I mention it in conversations, this has surprised enough people that I thought it deserved its own blog post.
As a bit of background for those unfamiliar with it: Unity is a software engine and toolset designed for making realtime, interactive, virtual 3D environments (usually games*). It provides many 3D essentials built-in, from physics simulations to lighting to controller input. Furthermore, Unity provides a robust interface for these systems through APIs, allowing developers to write C# code to manipulate these existing systems - or create whole new systems of their own. In fact, much of the online discourse around Unity is centered on the C# language: one of Unity's core selling points is being able to make games with minimal coding, so a non-trivial amount of the discourse is helping new developers make the transition from "no code" to "minimal code".
Given that developers have to write C#, one might assume that Unity itself is written in C#. That assumption, however, is flawed in two important ways. The first flaw is that C#, historically, hasn't always been the only scripting language. A decade ago, the engine supported the developer using their choice of any of three scripting languages: C#, Javascript, or Boo. To facilitate this, the engine was designed to leverage a language-agnostic framework, Mono*. It is only (relatively) recently that Unity has shifted to only supporting C#: a change that was precipitated by users and support groups almost exclusively using that one language.
The second flaw is the expectation that one's scripting language would influence the language for the core of the engine. It is actually quite common across a wide variety of domains (including games) to use a completely different scripting language compared to the main project. Lua, for example, is an extremely popular scripting language for games that support modding, but most (if not all) of those games are written in another language*. This separation provides a number of benefits, not least of which is that the underlying engine can be tailored to the performance requirements, while the scripting language choice can be tailored to end-users' needs. In Unity's case, this is exactly what happened: the (performance critical) core of Unity was written in C++, while the scripting layer favored more user-friendly languages (eventually converging on C#)**.
Interestingly, some Unity games, despite being scripted in C#, are actually compiled into C++. If the developer uses Unity's IL2CPP (an alternative to its Mono-based scripting backend), then the Unity Editor will compile all the games' scripts into C++ binaries (instead of Mono-compatable intermediate libraries). While I haven't personally used it, it is my understanding that IL2CPP allows developers to target platforms that cannot compile code just-in-time* - in exchange for losing access to certain features that hinge on said just-in-time compilation.
When I first started using Unity, I thought I was using an engine built on a framework that I largely understood. Over time, I've found that assumption to be quite inaccurate: Mono itself has some important differences versus Microsoft's .Net, but even then, that didn't explain many of the inconsistencies I saw. It wasn't until I finally understood that, at its lowest levels, Unity is actually a C++ engine, that things started to make sense. Where I once saw inexplicable design choices I now see a mirror reflecting the engine's C++ roots. It is my hope that now, having read this post, you too will better understand Unity's design, if only a bit.