A Closer Look at the Duality Engine

 

In today’s Closer Look we are looking at the open source C# based 2D game engine Duality.  The Closer Look series is a combination of review and getting started tutorial that is aimed at helping a developer decide if a game engine is the right choice for them.

 

There is also an HD video version of this guide available here.

 

First I need to start with a confession.  A few people mentioned Duality to me in the past and each time I dismissed it, very quickly.  An open source C# based, non-cross platform Unity-wannabe developed by a single guy?  Yeah right… pass.  These types of projects are a dime a dozen until people quickly realized that developing a product like Unity is actually a hell of a lot harder then they thought, even if they just focused on 2D.

 

Well, let me just start by saying I was wrong… very wrong.  A bit of a spoiler alert, but Duality impressed the hell out of me and I think it will impress the hell out of you.  There is one thing to be aware of right up front from that previous paragraph… “non-cross platform”.  Right up front this is the biggest flaw of Duality so no sense wasting a ton of time if this is a deal breaker.  That said, it’s not the huge problem it used to be as there has been a lot of work underway to make Duality cross platform.  It’s built on top of OpenGL and the entire core as well as all class libraries are now portable class libraries.  In theory this means, aside from the editor which is tied to WinForms, a duality project should be able to run on any modern C# capable platform with OpenGL support.

 

Getting Started

 

Getting started with Duality is easy but may add some complications for integrating with source control, updating or collaborating with others.  The duality download is the engine, and the tools AND your game.  When you spawn a new project in Duality, it downloads and sets up another Duality environment.  You can download the latest version right here. (That’s a direct link by the way).

 

The download is simply a zipped folder.  Extract it somewhere, it’s contents should look something like this:

image

 

Simply double click DualityEditor.exe to get started.  After launching and agreeing to the MIT license, you will be greeted by this window:

image

 

Dont worry, it should only take a few seconds depending on your internet speed.  A full install currently weighs in at around 120mb.  Once done downloading the editor Dualitor should now be loaded:

image

 

I suppose this is a good time to point out that you need to have Visual Studio 2013 or newer installed and with patches applied.

 

The Editor

 

The editor is extremely straight forward, let’s do a quick guided tour of it’s features.  It should be noted, the entire editor can be docked/undocked, hidden or shown as desired, so the layout is completely up to you.

 

Editor View

image

 

You can have multiple instances of the scene view running and you switch between them using the tabs at the top:

image

 

You can also rearrange the views however you wish, such as:

image

 

In addition to the Scene Editor where you compose the entities that make up your scene, there are two other options available in this view:

image

Game View and RigidBody Editor.  The game view is like a running preview of your game, while RigidBody editor is for defining physics shapes, which we will see later on.

 

Scene View

This is your game’s scene graph.  This is where you can select the entitles that make up your scene as well as the components that compose them.  Additionally you can create new entities or add new components here.

image

We will cover this process in a bit more detail later on.

 

Project View

The Project View is essentially the assets that compose your game, things like images, fonts, audio files, etc.

image

New assets can also be created here, using either the right click menu or via drag and drop from Explorer.  We will also cover Project View in more detail later.

 

Advisor View

Advisor view is basically a context sensitive help, like a stationary and in-depth tool tip.  As your mouse location or keyboard cursor change, the context switches and content is updated.

image

 

It’s handy while learning your way around but will probably be turned off in short order to free up screen real estate.

 

Object Inspector

The contents of this window changed based on the currently selected item.  If an entity is selected in the Scene View, the properties of all the components that make up the entity are shown, like below:

image

 

While selecting an asset will show the corresponding editor, like this one for ttf font files:

image

 

Note in this case all of the values are grayed out because I selected one of the built in non-editable assets.  Note the font preview at the top of the window… neat.

 

Finally there is the menu and toolbar across the top:

image

 

This tool bar enables you to load the source in Visual Studio ( the C# icon ), compile + run, compile + debug, or preview in the editor.

 

All told, a streamlined and somewhat minimal but highly configurable editing environment.  I never once experienced a crash or lock up in my time with Duality, so at least for me, stability and performance seem pretty solid.

 

Creating a Game

 

So that’s the editor covered, let’s take a look at using it to actually create a game.  You may have guessed at this point that Duality uses a component based design.  The entities that make up your scene are in turn composed of components that provide that functionality.  The top level entity is called a Game Object and you can create one in the Scene View by right clicking and selecting New->GameObject.

 

image

 

The other options simply create a pre-populated GameObject for you.  Your newly created entity will now be available (and re-nameable) in the Scene View:

image

 

Now let’s right click our game object and add some components to it.  We want to be able to position our object in the world, so let’s first add a transform component.  Simply select New->Transform.

image

 

Let’s make this a sprite, right click again, then select new->Graphics->SpriteRenderer.

image

 

Your entity should now look like:

image

 

Plus if you look over at the editor window, you will see a sprite now appears using the default sprite:

image

 

While in the object inspector you can now edit the two components attached to our object:

image

 

You can also edit the translation, rotation and scale of the sprite in the editor view using one of the cleanest 2D widgets I’ve yet experienced:

movewidget

 

Now let’s add our own sprite, simply drag and drop from Explorer to the Project view, like so:

DragDrop

 

Now if you select the newly created pixmap, you will see it’s settings in the Inspector window:

image

 

Notice like fonts there is a preview of the asset file.  Now we can update our SpriteRenderer’s SharedMaterial property by dragging our new asset over, like so:

ChangeTexture

You will notice that Duality automatically created two new assets, a Material and Texture definition.  You can go a great deal deeper if you wish, for example changing the draw technique that is used to renderer the material to screen, which in turn you can drill down and define your own vertex and fragment shaders, etc.  The details are nicely hidden away from you, but if you want to drop down into the technical details you easily can.  That is beyond what we are going to cover today however.

 

Now we have created a sprite game object that can be positioned in the scene, now let’s go ahead and make it do something.  Let’s add a physics RigidBody component to it by selecting New->Physics->RigidBody:

image

 

As you can see in Inspector, once the rigid body is added, there are a number of values you can configure in the component:

image

 

In this case however we are going to stick to the defaults.  You can also edit the physics bounding shape if desired.  With the game object selected, in the editor view switch to RigidBody Editor, and you can now define a new rigid body shape.

rigidBody

 

Notice will editing the rigid body, the Inspector window has yet a different set of options available:

image

 

Now, lets go ahead and preview our handy work.  If you want to see a more accurate result, switch to Game View, then click the play icon:

image

 

And you should see:

Running

 

So we’ve got a physics enabled sprite being drawn with almost zero effort, pretty cool.

 

The Coding Experience

 

So, that’s the editor down.  Let’s take a look now at what the coding experience is like.  Click the C# icon to load your project in Visual Studio:

image

 

Your starting project is extremely straight forward:

image

 

Your “game” itself is actually implemented as a plugin, that is what the class CorePlugin.cs is.  The contents are incredibly sparse:

using System;  using System.Collections.Generic;  using System.Linq;  using System.Text;    using Duality;    namespace Duality_  {    /// <summary>    /// Defines a Duality core plugin.    /// </summary>    public class Duality_CorePlugin : CorePlugin    {      // Override methods here for global logic    }  }  

 

This is where the global logic and variables of your application reside.  The majority of game logic however will be in the form of components.  A default component is created, YourCustomComponentType.cs, which contains the following code:

using System;  using System.Collections.Generic;  using System.Linq;    using Duality;    namespace Duality_  {    public class YourCustomComponentType : Component    {          }  }  

 

That’s about it, not a lot of boilerplate code required.  Do a compile for your project in Visual Studio.  Now if you go back to editor and add a component to a GameObject you will already see this type is available through the powers of reflection:

image

 

Now let’s add our own new Component, this one for adding WASD controls to our entity.  Simply create a new class called WASDControl.cs with the following code:

using System;  using System.Collections.Generic;  using System.Linq;    using Duality;  using Duality.Components;    namespace Duality_  {      [RequiredComponent(typeof(Transform))]      public class WASDControl : Component, ICmpUpdatable, ICmpInitializable      {          Vector2 position;            public void OnInit(Component.InitContext context)          {              position = new Vector2(0, 0);          }                    public void OnUpdate()          {              var transformComponent = this.GameObj.GetComponent<Transform>();              position.X = 0; position.Y = 0;                if (DualityApp.Keyboard.KeyReleased(Duality.Input.Key.W))                  position.Y -= 10f;              if (DualityApp.Keyboard.KeyReleased(Duality.Input.Key.A))                  position.X -= 10f;              if (DualityApp.Keyboard.KeyReleased(Duality.Input.Key.S))                  position.Y += 10f;              if (DualityApp.Keyboard.KeyReleased(Duality.Input.Key.D))                  position.X += 10f;                transformComponent.MoveBy(position);          }            public void OnShutdown(Component.ShutdownContext context)          {          }      }  }  

 

This example illustrates a couple of things.  First if your component requires the existence of a certain component, you can define that using the RequiredComponent attribute.  Next you can see I inherited from two additional interfaces, ICmpUpdatable and ICmpInitializable.  The first class tells Duality that your game implements Update() and should be called each frame.  The second indicates you have initialization or cleanup code and thus implement OnInit() and OnShutdown().

 

Otherwise the code is quite simple.  Your component has access to it’s parent game object in the form of GameObj and can access child components using GetComponent().  The component also has access to the engine itself through the DualityApp class, which is used in this example to poll the keyboard state.  This component can now be added in the editor to any game object that has a transform component making for easy code reuse.

 

Given the amount of space already used, I can’t go into extreme detail about what Duality can and can’t do from a programming point of view, but you can get a pretty good idea from looking at the class reference documentation.  The video version also has a bit more in depth on the coding experience if you are interested.

 

Documentation and Community

 

The primary documentation for Duality is the wiki available here.  It’s a collection of tutorials covering most of what you need to get started.  Perhaps most important piece of documentation is the reference material that is included with the engine, however I could not find an online version.  The reference material is fairly comprehensive and while a bit light in places, for the most part has what you need well documented.

Another aspect of Duality is the samples.  These can be downloaded directly within the editor via File->Manage Packages:

image

The code for these projects is also available on Github here.

The community is small but active.   The primary source of help is going to be the forum.  Fortunately it seems like the vast majority of questions receive and answer and the author seems quite active.  Of course the source is available as well.

 

Summary

 

I have to say, I love being surprised by engines and Duality certainly surprised me.  It is a very focused 2D only engine and the requirement for Windows for a development machine.  This is of course going to turn many off.  For the rest though, Duality represents a great, free, open source C# 2D engine.  It’s polished, well documented, well supported and well designed.  There’s not much more you can ask for in an engine.

 

The Video

 

Programming


Scroll to Top