Saturday, January 5, 2013

Is .NET and XNA mature enough for AAA game?

On 28th November we finally released our main title MinerWars 2081, the most technically and visually precised game written entirelly in .NET and XNA. What is our experience with these technologies and how they helped us? I will conclude everything in this post mortem article.



Why .NET + XNA?


First versions of the game were written by Marek Rosa as technological demos of destructible environments, and were written in C++ and OpenGL. After great public reception Marek decided to use this technology to create commercial game, and that's how MinerWars idea was created. In that time, three years ago, there was no suitable engines available, like CryEngine or UDK today (regarding to our requirements, price, development effectivity and dynamic environment support). It was time when Unity was in beginning and its quality was just not enough for MinerWars. To choose between quality and development effectivity, Marek finally picked XNA and .NET as his main technology. It was the best possible solution in the time, and was heavily supported by Microsoft marketing, where XNA was presented as future game platform.



My participation


The game development with .NET and XNA lasted for two years, there were involved 1-7 tech programmers, and up to 6 scripters using C# for scripting too. Most time I worked as Lead programmer (render, lighting, object management, game logic), also I was responsible for application architecture and design, writing and authorizing prototypes, but also hiring new programmers, managing their work and checking the code quality after them. With all these experience I will try to conlude my thoughts about .NET and XNA, even Microsoft and other related products. All these are my personal opinions made during the time, and I am willing to change them if anyone is willing to persuade me :)


Pros of commercial game development in XNA and .NET


Let's begin with better things. .NET and even XNA surely have their pros in game development. It should be mentoied that in beginning, our idea was to create game for both PC and XBOX360 platforms, later appeared, that XBOX will be harder nut that Microsoft presents. Because of this, only PC related issues are listed here.

- Effectivity

With managed environment, C# language and XNA, development of the game is going really fast. Development of small game (2D arcade, 3D chess..) can be finished in weeks. Many solutions in XNA are already premade and ready for use. Just find it, know it, and use it.

- Managed code debugging

Debugging variables, code flow or crashes is usually very straightforward and user-friendly. Together with some other anti-bug solution (unit tests, buddy checking, auto-builds/runs) it is possible to generate very low bugged code.

- Memory safety

No more access violation or reading corrupted memory. Only (big) problem which remains are memory leaks.

- Tutorials and samples

There is many tutorials and samples for XNA (2-4.0) and for .NET. You can find basic and advanced solutions on servers like http://stackoverflow.com/, http://xboxforums.create.msdn.com/forums/, or just reading articles from Shawn Hargreaves.


Cons of commercial game development in XNA and .NET


- Microsoft support

It's dead. Microsoft stopped development of XNA for PC platform and day from day they stopped all official support. They are not fixing bugs, they are not releasing new versions. Very "fair" to many people stuck on this technology (and sad for companies which built their engines on XNA).


- Performance

In the past, Microsoft presented .NET great performance on running Quake 2 in managed code. It was year 2003 and nowadays, this kind of games is able to run even on mobile platforms. .NET performance is highly inadequate to run engines with same quality and features similar to CryEngine etc. The sad truth is that if Microsoft continues .NET and XNA development, it could be different. Why is it not possible to compare managed XNA engine to C++ native engines?

  1. Compiler - C# compiler optimizations are very naive comparing to C++ optimizations. Compiler is using slow virtual calls in all non static cases. The difference between Debug and Release performance is minimal.
  2. Inlines - It is not possible tell the compiler which method to inline and which not. It depends on internal logic which chooses inlining rarely.
  3. Garbage collector - there is no possibility how to alter its behavior, how to access/profile allocations in realtime, how to disable/change allocator or write custom one (plus it is not recommended at all).  
  4. Allocations all around - altough best practice to write performance applications (game) is to avoid any allocation, many C# or XNA methods do allocations and there is no way how to avoid them. You just must not use them. For example - XACT in XNA is full of allocations, lambda functions do allocations, adding/removing event handler, all string (even some preallocated Stringbuilder) operations, accessing dictionary with struct as a key and many more.
  5. SIMD - C# compiler does not use even single one SIMD instruction. That's deadly for vector+matrices calculations, which are used most in games development
  6. XNA is not wrapper - XNA is framework with additional logic, which on many places costs performance. You can see XNA performance here (10x slower against native implementation) http://code4k.blogspot.cz/2011/03/benchmarking-cnet-direct3d-11-apis-vs.html

- XNA Bugs and flaws

  1.  XNA is stucked on DirectX 9 - You can use nothing from nowadays high-end graphics cards. It is not supported on Windows 8.
  2. Device lost - this situation is solved strangely in XNA 4.0 (even when it worked fine in XNA 3.0) and resources are needed to be always reloaded, even when XNA should manage it.
  3. Multi monitor support - some multi monitor configurations are unstable and can cause XNA crash (or end in neverending DeviceLost loop)
  4. Reduced DX9 features - because of compatibility with XBOX 360, XNA developers decided to disable some features in XNA (ie. reading depth buffer, hw. occlusion queries for float buffers, separate depth buffer, optional parameters when creating resources and many more). All these features are fundamental if you want to create high-end rendering engine.
  5. Audio problems - XNA crashes when some disabled audio output is set.

- Out of memory

The problem with memory when developing .NET game is always one - it is always low. If you are out of memory, it is difficult to use any profiler, because it crashes on out of memory too. The only way to debug it is to use SOS commandline tool or use profiler, which is able to access crashed process (http://memprofiler.com/ Proffesional). It is difficult to track all references and keep them clean during the development. Moreover, there can be problems with Large memory heap fragmentation or you can even get out of native process memory.


General conclusion

Altough the game can be developed very fast in .NET and with XNA, there is a big price in performance penalty and memory problems. Fortunatelly, there are some projects now which can reduce this penalty, because they are just wrappers above DirectX. See http://sharpdx.org/ or http://slimdx.org/. Some projects also target to replace XNA, and make its better and faster alternative (http://anxframework.codeplex.com/http://monogame.codeplex.com/)

Because of .NET design and compiler problems, the managed game will be never as fast as native C++ game. But thanks to projects like SharpDX and SlimDX, more effective and more advanced game/engines can be created, still with great development effectivity. And I am looking forward to them.