It is our experience that having a quality tool set is crucial to the development process. The last thing anyone wants is to work with tools that don’t quite get the job done; otherwise, you end up getting frustrated because what should have been a simple button press turns into additional time spent to work-around the quirks or deficiencies of the tools. We’ve all been there and we all know the additional stress and pain it injects into a project. This is why one of our core tenants from the beginning has been to invest the time required to create good, complete tools.
We decided to use C# as our primary language for building our development tools. We feel that this has been an excellent choice for a few reasons:
1. Tool Requirements
It is important to recognize that tools do not have the same requirements as the engine. Tools need to be performant, but not in the same sense as we think of for the game engine; for example, it is completely acceptable for an “interactive tool” to include busy cursors and progress bars. The same argument goes for memory usage and management.
Consequently, these factors point us away from C++. While C++ provides us with the facilities to be close to the metal to manage the nitty-gritty details of our application, this level of control comes at a steep price: increased developer responsibility, which often equals increased development time. As much as we love C++, it’s just not the right language for the vast majority of our tools.
2. Iteration Time
C# is a great language to use for writing both console and GUI applications. The language itself provides the typical mechanisms used in tools, like events and delegates; and it has a well-defined, robust set of libraries (collections, file system, controls, threads, etc). These attributes reduce iteration time substantially.
Simply put, C# makes building tools easy and convenient to get the job done.
3. Domain Separation
Using a different language for our tools and engine code bases creates a clear boundary between the two domains. This self-inflicted “language barrier” helps keep us honest about not mixing tool / editor code with engine code.
Certainly, we know that the boundary can be crossed with the help of
PInvoke or C++/CLI, but doing so requires additional steps that serve as a useful deterrent from the temptations of “just for now” hackery. Instead, when we need a portion of our tool to utilize engine code, we wrap that functionality in an executable that can be invoked from within the tool.