Modern C# on Game Consoles

C# has long been a popular language for developing video games. Its use dates back to the Xbox 360 era when Microsoft released the proprietary XNA game development framework. The framework allowed C# games to run on desktops and consoles, a massive attraction for game developers.

Since then, engines like Unity and frameworks like MonoGame and FNA have further expanded C#’s popularity for cross-platform game development. With some recent announcements, its future is further solidified as a language of choice for developers.

Current Generation

Today's two key technologies for compiling C# for game consoles are BRUTE and IL2CPP.

BRUTE is a .NET IL bytecode to portable C++ transpiler initially developed by Tom Spillman. Both FNA and MonoGame use it to target console platforms, and its use is seen in hundreds of games on consoles, including Stardew ValleyTowerFall and Axiom Verge.

IL2CPP is Unity's proprietary technology used to compile games to multiple platforms. It also transpiles IL bytecode to C++. Its use is also seen in hundreds of games on consoles, including Hollow KnightCuphead and Ori: Will of the Wisps.

For Xbox platforms, FNA, MonoGame and Unity can alternatively utilize the Universal Windows Platform (UWP). However, UWP was designed to be compatible with the discontinued Windows Phone platform and has some performance limitations. UWP was also officially deprecated in 2021, and Xbox will eventually stop accepting UWP-based game submissions. While there is no timeline for this, it is strongly recommended not to rely on UWP for game development.

State of Technology

BRUTE has performed well for a long time. The hundred of games using it is a testament to that. However, to use BRUTE your game must target .NET Framework 4.5 APIs. As time passes, this becomes increasingly limiting for game developers who want to use modern C# and .NET. Version 4.5 was originally released in 2012, and both .NET and C# have significantly changed since then. In addition, the version of ILSpy, which BRUTE depends on for bytecode decompilation, is outdated and updating it to a modern version (for newer .NET support) would require a significant rewrite.

At the time of this blog post, Unity’s IL2CPP requires targeting to .NET Standard 2.1 and C# 9.0 or lower. (I’ll spare you the history of Mono, .NET Framework, .NET Core and why .NET Standard exists.) While this is more modern than BRUTE, it is not entirely in line with current C# versions and comes with some language feature restrictions.

Since both technologies compile to C++ first, a second compilation step is required to run on the console platforms. As a developer, long compilation times significantly impact productivity - not ideal when iterating on gameplay and working against deadlines.

BoehmGC

One important note on how BRUTE and IL2CPP work is that they both use BoehmGC as their garbage collector. I'll explore garbage collectors in a later post, but for now, you need to know that they manage your C# game's memory. To do this, they pause the running of your game to clean up memory. 

BoehmGC has been used in software for over 30 years. It is a portable garbage collector designed to run on any platform. However, it comes with some limitations important to game development; it is not multi-threaded, it is non-compacting, and it is a generic garbage collector.

Non-compacting means that if your memory space becomes highly fragmented, your game may not be able to allocate sufficient memory when required, causing a crash.

Non-multi-threaded means that when the garbage collector pauses the application, it can't take advantage of multiple CPU cores. This can result in longer pauses causing stutters in gameplay. BoehmGC does have a partial workaround to this called incremental mode, allowing it to scan the memory over several frames. However, the pause still has to happen during the cleanup operation. So while it reduces stutters, the stutters can still occur.

This implementation is one of the reasons developers encounter performance and stability issues when porting their desktop C# game to consoles - the desktop .NET runtime uses a garbage collector explicitly designed for .NET, whereas BoehmGC is designed for generic use.

So while the current solutions work well, developers would ideally be able to target modern C# without worrying about different .NET versions, C# language feature support and garbage collector behavior. With each new .NET release, what is possible on the desktop should be possible on game consoles.

Next Generation

In 2014, Microsoft began to shift .NET’s development to an open-source and cross-platform process. The runtimelab repository was created for experimental .NET technologies as part of the open-source development process. An interesting experiment was a technology called NativeAOT (previously known as CoreRT). NativeAOT provides ahead-of-time compilation for .NET applications to Intel and ARM architectures and utilizes the same garbage collector as .NET on desktop. It also has the added benefit that it doesn’t need to compile to C++ first and then to native - dramatically speeding up compile times.

To stay in line with modern .NET and C#, it would make sense to base a solution on the open-source .NET repository itself and NativeAOT appeared to be a good candidate to achieve this.

Fortunately, Caleb Cornett successfully ported NativeAOT to Nintendo Switch using a preview snapshot of .NET 7.0. This was based on previous CoreRT porting work by Ralf Kornmann.

Yesterday, FNA announced that NativeAOT and .NET 7.0 are running on all three major console platforms. And so, it is now possible to use modern C# for true cross-platform game development!

In fact, Alchemic Cutie was the first NativeAOT-based game to pass certification on Nintendo Switch. We worked closely with Caleb Cornett, Ethan Lee and the FNA community to contribute patches which prepare NativeAOT for production use on the platform. (Side note: A huge thank you to everyone who collaborated on porting).

We will continue to contribute to the PlayStation and Xbox ports of NativeAOT to prepare them for production use also. Our goal is to help developers so that NativeAOT is an out-of-the-box experience for porting to consoles.

Conclusion

C# has been a popular language for game development for over a decade, and its future has never been brighter. We expect continued innovation and support for the language on game consoles in the coming years.

If you’re seeking a partner to bring your C#, MonoGame, FNA or Unity title to game consoles, reach out to Viridian Software today and seamlessly bring your game to all platforms.

Previous
Previous

Game Stutter and Garbage Collection