A .NET Dev Learns Unity, Part 1—First Impressions
Welcome to "A .NET Dev Learns Unity," a series of blog posts in which I explore the world of game development using the Unity game engine. I've wanted to get into game development for some time now, and Unity promises a robust, mature platform for creating both 2D and 3D games. Games can be published to an impressive array of platforms—Windows, Mac OS X, Linux, iOS, Android, web browsers, game consoles such as PlayStation 3 and Xbox 360, and more. And most compelling, from my perspective, is that it uses C# as a primary scripting language.
A little about me: I've done professional .NET development for a little over four years. For the first year and a half or so I worked with ASP.NET, and since then I've developed Silverlight and WPF applications. Before all that I wrote a couple shareware applications for OS X using Cocoa and Objective-C, did some web development with PHP, and dabbled in languages such as Python, C++, and a bit of Lisp. But the bulk of my experience is with C# and .NET, so Unity seems like a great fit.
What I have not done is any serious work in game development or design. I've had plenty of ideas over the years, but until now have never made a serious attempt to realize them. And while I love software development in general, game development has always been a goal of mine. Do I expect my time with Unity to drastically alter the course of my career? Not necessarily, but if nothing else, I'll have some fun on the side and further hone my C# programming skills.
What this blog series is and is not
One thing I've noticed so far is that the majority of Unity learning materials on the Web are videos. I'm sure that's great for those coming to Unity with graphics and game design experience already, but I much prefer to learn by reading. You can go at your own pace, you can pause and study code, and you can easily go back to review things. Also, the bulk of the videos I've found focus on the visual and presentation aspects of Unity. This makes a degree of sense—they are called video games, after all—but as a developer, I have more interest in the coding aspects of Unity, how to make things work under the hood. My philosophy is always to make something work before making it pretty. Just as I'd rather use an ugly but reliable application over the opposite, I'd rather play an ugly but fun game over one that's all flash and little substance. And to be honest, I'll likely solicit the help of others for any serious graphics and sound work, should any project of mine reach that point.
But as I've said, so far I haven't found much in the way of written tutorials or learning materials targeted at developers. This is an apparent void I'd like to help fill. So this blog series will chronicle my experience as a developer learning Unity. I'll share useful developer-oriented resources I find and pass along any insights I have. I expect readers to have some development experience already, especially with C#, but I'll try not to wade too deep without some explanation first.
I don't intend for this series to be a set of tutorials. Rather, at least for starters, it will be a set of observations from a programming standpoint. But given the aforementioned lack of obvious programmatic resources, I imagine later entries will adopt a heavier instructional tone. But we're just starting out; let's see where this goes.
Initial thoughts on Unity
Written tutorials and resources
These sites have the tutorials and articles I've been learning from so far:
- Catlike Coding: https://www.catlikecoding.com/unity/tutorials/
- Unity Gems: https://unitygem.wordpress.com/
Specifically, I've worked through the Clock and Runner tutorials at Catlike Coding, and read the articles "Coding Conventions" and "Common Unity Gotchas" at Unity Gems. They're pretty well written and do a good job of covering the basics. Unity Gems has articles on more advanced topics that seem likely to come in handy later. I'd love recommendations for other tutorials and articles, particularly written ones.
My initial thoughts on Unity after working through these learning materials follow. Take note: what follows is primarily observation, inference, and conjecture. I've not yet performed much in-depth research into the internals and official documentation of Unity, so I could easily be mistaken about certain things. I welcome any corrections or pointers to additional information.
Creating and manipulating scenes of game objects
For starters, let's talk about Unity's object design patterns and creating scenes with the visual designer.
Unity favors object composition over inheritance. Game objects are laid out as a tree, with each object containing zero or more child game objects. All game objects appear to have the same type. Distinguishing one game object from another are components attached to each object, allowing one to specify transformations, light sources, materials, particle engines, arbitrary scripts, and so forth. This allows a high degree of flexibility, giving one the ability to mix and match disparate components without the constraints of a complex inheritance hierarchy. On the down-side, this can make modeling is-a relationships difficult, because scripts must interact on components directly rather than on the higher level abstractions of game objects themselves. It will be interesting to play with this and see what sorts of design patterns emerge and what forms of abstraction and encapsulation are practical.
Unity's visual designer provides a GUI for creating a hierarchy of configured game objects and saving them as a scene. It reminds me of Xcode's Interface Builder. Unlike imperatively creating objects in code, or declaring objects in a markup language such as XAML, the designer allows one to create objects live, establishing their relationships, adding components to them, and setting their initial property values. Saving the scene saves all of these objects—probably through some form of serialization—and when the scene is loaded while running the game, the objects get loaded with their state and relationships intact.
The inspector for editing objects is especially interesting. For a selected object, it displays a panel of controls for each attached component. Each panel contains controls for every public field and property in the component, providing a type-appropriate control to set the field or property's value. Even non-primitive properties can be set—one can drag an object instance from the hierarchy into the field, creating a reference to the object. The inspector works for both preexisting components and user-created scripts, presumably using reflection to find each public field and property and the type of each to display the appropriate controls. It also performs friendly formatting of property names—a property in a script component named myAmazingProperty displays in the inspector as My Amazing Property. This results in a bit of inconsistency between the designer and script code, but I appreciate the effort.
Unity would be pretty limited if one had to create upfront every conceivable object instance in a scene. But game objects are composed from components, not defined as new classes. Even custom code resides in a script component attached to a generic game object. As a result, traditional instantiation of new game objects during runtime is of little use, because the new game object instance would lack any defining characteristics. Therefore, Unity follows the Prototype design pattern. After creating a game object and setting all its component properties to appropriate defaults, one adds the object to the scene's assets as a prefab. Then, whenever one needs to create a new instance of the game object during runtime, one calls the static method UnityEngine.Object.Instantiate on the prefab instance, which returns a clone of the prefab and all its children. One can then use this new clone of the prefab without affecting the original prototype.
In addition to prefab objects, Unity allows saving other resources as reusable assets in a scene: scripts, materials, models, and so forth. Most of these can be edited with the inspector in the same way as game objects. For scripts, Unity delegates editing to an external editor, and provides a custom build of MonoDevelop as the default editor. MonoDevelop provides a decent free alternative to Visual Studio, though one can change the default editor if desired. (Expect elaborate and hurtful diatribes about MonoDevelop versus Visual Studio in future entries, after I've spent more time with it.)
Differences from .NET conventions
My initial thoughts conclude with a pedantic rant, but this goes against years of practice writing .NET applications, and I can't not say anything. The convention in Unity is that public and protected property and field identifiers begin with a lowercase letter. Method names still begin with a capital letter, and capitalization otherwise follows the standard .NET norms, but properties (and fields, though those typically shouldn't be public) buck the trend. Granted, .NET is one of the few programming environments I've encountered where class member identifiers begin with a capital letter by convention, but the convention is useful. In a method definition I can tell at a glance whether an identifier refers to a local variable or a class-level property, similar to how private fields often begin with an underscore to make their scope obvious. And beyond that, why not make method names start with a lowercase letter too? It's inconsistent. Speaking of inconsistency, and perhaps worst of all, the Mono framework, based on the .NET framework, uses the standard .NET conventions; as a result, some property names start with a capital letter, whereas others start with a lowercase letter, making code look messy. Insight into this design choice is welcome. I don't mean to imply one style is more correct than another, but for me, the inconsistency results in cognitive dissonance that distracts me from writing code and makes me cringe a bit every time I follow the Unity convention.
Conclusion and topics for the future
This concludes my initial impressions of Unity. Again, I haven't yet delved very deep, and I may well be wrong on certain points. As I learn more, I'll pass along corrections and additional insights. Again, please feel free to correct any mistakes I've made or to provide more detailed information. My intent is not to misinform, but merely to document my learning process.
Now armed with knowledge of the basics and the mental model of how Unity works that I've described above, I intend to experiment by making a very simple game of my own. In particular, I wish to see how well my standard .NET programming techniques translate to the world of Unity. Some of the topics I intend to explore include:
- Using public properties to encapsulate private fields
- Using the INotifyPropertyChanged interface and PropertyChanged events to simulate data binding, similar to frameworks such as WPF
- How the Singleton design pattern can function in Unity
- The practicality of encapsulating components at the game object level (is it possible? Is it worth it?)
Thanks for reading. I hope to report back soon.