Gamasutra: The Art & Business of Making Gamesspacer
arrowPress Releases
July 30, 2014
PR Newswire
View All





If you enjoy reading this site, you might also want to check out these UBM Tech sites:


Opinion: Separation Of Gameplay
Opinion: Separation Of Gameplay
December 12, 2011 | By Alistair Doulin

December 12, 2011 | By Alistair Doulin
Comments
    9 comments
More:



[In this reprinted #altdevblogaday-opinion piece, Bane Games' Alistair Doulin discusses separating gameplay from code to make it "engine agnostic", and explains why others should adopt this approach.]

I've worked on three different game engines and all have had gameplay and engine intertwined throughout the source code. In Unity, all game objects inherit from, MonoBehaviour giving them full access to the power of Unity (and forming a hard link between game and engine).

Recently, I've moved away from this approach to a better "separation of concerns". I completely separate out the gameplay making it engine agnostic. This has worked well and I plan to use this approach for most of the games I create in the future.

Today I discuss this separation of gameplay and why I recommend others make the switch.

Why?

Why would you want to separate out the gameplay from the rest of the game? There are a few main reasons for this:
  • Gameplay code varies widely between different games. Whereas other systems like rendering, audio, animations and input have many similarities between different games. (e.g. while Battlefield 3 and NFS: The Run share an engine, their gameplay is substantially different).
  • Gameplay code has different ownership to the other systems in the game. Most teams are split into gameplay and engine divisions. These two areas require different skill sets which is why there is specialization in each. Often the size of the gameplay team will be similar in size to the engine team.
  • Designers deal solely in terms of gameplay and so they should. Designers should not be concerned with shaders or specific input code. Separating this code out simplifies their job and protects them and the engine from each other.
  • Allows unit testing specific to gameplay code. As the test suites are gameplay focused, they are simpler and easier to maintain.
  • "Finding the fun" is one of the hardest and most important parts of game development. By separating out gameplay developers can focus solely on this task without worrying about other engine related issues. By dealing with less code, developers have a better velocity to make changes and prototype new ideas throughout development.
How?

We're using Unity and C# for our game development. We split the gameplay out into it's own library (a .dll specifically). This library has no reference to Unity and is completely engine agnostic. In theory, we could swap out Unity for XNA or another engine that is able to communicate with a .NET library.

The game engine then "includes" this library and uses it for simulating the game world. In Unity this is as simple as dragging the .dll into the project and you instantly have access to all it's public types.

One option is to make all access from the game engine into the library through interfaces. This gives you the best separation of concerns and completely decouples the game engine from the implementation of the gameplay.

I did this for the first game that used this technique but have since moved away from it. I highly recommend having all communication through an interface for larger games and teams.

I've also used this technique in an XNA project which was also a simple process. Simply add a reference to the gameplay .dll and start coding against it.

Scripting Languages

This separation is often achieved through scripting languages. Certain behavior within the game is exposed to designers through a scripting language like Lua. I've done this on a number of projects and this separation works well. I've also spoken about why I think C# should be used as a scripting language.

Separation of gameplay is an extension to the regular scripting language breakup. Separation of gameplay flips the classic scripting language paradigm on it's head.

Rather than exposing some functionality of the game engine to designers and gameplay programmers to create the game world. We let the designers and gameplay developers create the world and engine developers use this world.

This frees both teams up to work at full velocity initially as they build the ground work of the game. Both have set functionality they must achieve and can communicate through a simple, well defined interface. Designers can focus on implementing fun gameplay while engine coders work closely with artists to get the look and feel they want from the game.

Engines like Unity and Unreal all gameplay code is already in a scripting language (Unreal Script and C# vs the engine's C/C++ code). However I'm arguing for taking this a step further and even within these scripting languages we create a separate library independent of any of the engine specific code. We then have three main domains within our game:
  1. Gameplay specific code (eg Player ship and Torpedo)
  2. Engine code specific to this game (eg Taking raw input and passing it in a nice form to gameplay specific code or shaders)
  3. Engine code (for Unity and Unreal this is the C++ code we generally don't access)
Negatives

I did find a few downsides to this approach. For games where game engine and gameplay ARE tightly linked, there can be a lot of duplicated data. As the gameplay code is unaware of the engine data structures like transform must be duplicated in the gameplay code. This increases memory usage and processing as the data structures are converted.

Another downside is that some useful features of the game engine are not accessible to the gameplay. Two key features of Unity that would have been great to use were triggers and coroutines. Once again, code duplication is required if the gameplay is to use these features. (See future plans below for a solution to these issues)

Two Worlds

In effect, there are two instances of the game world. A gameplay specific instance and an engine/rendering specific instance. For complex games this separation is a good thing as it frees engine developers to store the world in their own optimized data structures.

This decoupling also simplifies the process of multi-threading the game engine as there is a distinct breakup between gameplay specific code and rendering/input code. I've worked on a large project which made this split after a multi-year development and while it was painful to implement once complete the teams velocity increased significantly.

Unit Testing

I spoke about unit testing in my last post and this is one of the major advantages of separation of gameplay. You can easily unit test the gameplay itself and have a suite of tests specific to making sure the gameplay is "correct". When unit tests deal only with gameplay they can be simpler and higher code coverage can be achieved.

One area I am looking at in the future is formally turning the game design document into a suite of gameplay specific unit tests. The gameplay team have complete ownership over the gameplay code and the test suite that tests it.

Future Plans

There are a few areas I plan to experiment with in the future that I haven't had the opportunity to yet. The first is solving the issue of duplicated data between the gameplay and game engine. My thoughts on solving this problem are for the gameplay to have a reference to the game engine data structures where appropriate.

For Unity3D, this would be as simple as including the UnityEngine.dll. Spatial data structures (Vector3, Quaternion, etc) can then be used directly in the gameplay. This breaks some of the abstraction between the gameplay and game engine, but if done sparingly, I think it will add a lot of value.

Specific to Unity, I'm going to experiment with creating MonoBehaviour entities within the gameplay as well to see whether this works and how badly it breaks the abstraction.

As I mentioned with Unit Tests, I'm going to look at ways of formalizing the game design itself into a suite of unit tests. I'd like to experiment with Domain Specific Languages (DSLs) to make this as simple a process as possible for game designers. A DSL would also let them speak in their own language.

I've experimented with fluent game design in the past and this is another area of interest for me.

Conclusion

What are your thoughts on separation of gameplay from the rest of the game code? Is this already achieved with scripting languages or do you see extra value with allowing gameplay developers to create the entire gameplay model themselves and have engine developers use world through an interface?

[This piece was reprinted from #AltDevBlogADay, a shared blog initiative started by @mike_acton devoted to giving game developers of all disciplines a place to motivate each other to write regularly about their personal game development passions.]


Related Jobs

Technicolor
Technicolor — Austin, Texas, United States
[07.30.14]

Core Systems Engineer
CCP
CCP — Newcastle, England, United Kingdom
[07.30.14]

Senior VFX artist
Turbine Inc.
Turbine Inc. — Needham, Massachusetts, United States
[07.30.14]

Product Marketing Manager: Mobile Games
InnoGames GmbH
InnoGames GmbH — Hamburg, Germany
[07.30.14]

Software Developer Analytics / Big Data (m/f)










Comments


B Reg
profile image
Interesting, thank you for this great article.



Being active as a freelance webdeveloper myself, I know of the importance of separation of data, visual presentation and mechanics. It's kind of odd the read this principle to be rather new in game engine development.

Alistair Doulin
profile image
Thanks Bauke. I came up with the idea after my time as a web developer also. After working with ASP.NET MVC I fell in love with the separation of concerns and looked at how that could be applied to game development

Gil Salvado
profile image
Even though I'm not a programmer myself, it sounds reasonable to me because of its modular system. So far, we've always had the most problems with hard coding due to it's inflexibility. And the code created cannot be easily re-used for another project, which produces a double work afford that needs to be avoided at all cost.

Jonathan Withey
profile image
Something like the MVC pattern and it makes sense, some code examples would be nice.



As a devils advocate criticism, is your practical example an abstraction too far ? I mean, Unity itself is an abstraction to allow game creation, it must itself seperate it's rendering and *engine* parts from its components and game parts (hence it can export to diferent platforms). In some ways, that is its purpose. To port, you could just implement the interfaces that Unity itself uses.

Alistair Doulin
profile image
From my personal experience it didn't take abstraction too far. I found it made for a cleaner game that was easier to create and maintain.



I completely agree that porting is not a major strength of this technique in practice, it's just a nice byproduct.

Marc Audouy
profile image
I agree in principle but in practice you soon run into performance problem. to do a simple game it is fine but if you do a big AAA title on console these added layers will become costly very soon. For instance how NPCs target different objects in the world depends on your gameplay, but the various collision checks and raycast needed are so dependant on the engine that trying to abstract them out too much will prevent you from doing much needed optimisations.

Artur Correa
profile image
I have been using this approach since I started writting an engine .

My engine's core is based on Ogre3D for rendering, ODE for physics, Open AL for sound and Direct X for input. The Game engine is an executable file , and the game is a DLL that the engine loads at its start.

The entire gameplay code is enclosed on the DLL and it uses well defined interfaces to communicate with the engine in a generic way. It never touches details of ogre or the other libraries.

The separation works so fine that the gameplay developer even does not need to install SDKs for the dependencies The game is a separated project.

The difference is that I don't use scripting language for gameplay programming. All the gameplay code is written in C++, and honestly I think it worth , because

the gameplay code is so small that it compiles very fast, and it is easy to change.

Also , Ogre provides a separation between art and gameplay, by using a script language for materials , shaders and effects definition.

The bad side effect is that, by defining the interface between the gameplay and engine, we usually cut out features provided by the core. Ogre is a very powerfull renderer and scenegraph manager that, I confess, is very underused by my engine.

Lior Tal
profile image
I am all for separation of concerns and keeping code in its correct layer, not leaking to others.



I am still however failing to understand your concept of a "Gameplay" dll, since gameplay is a system that is cross cutting and needs access to most if not ALL of the game's systems.



How can you achieve this sort of encapsulation of the game engine that is running and keep your gameplay in one place without knowing anything about the engine?

Artur Correa
profile image
In fact, the gameplay dll must be made upon a conceptual view of the engine. this conceptual view is provided by the interface between the dll and the engine. This minimal relationship must exist. In a nutshell, The gamplay code must know wich engine it is made for. but it is only necessary to know how the engine works in terms of game play, and not in terms of technology.



For instance: Supose that is the code of a game object, written for the gameplay dll.



//Game entity initialization:



void EntityStartup()

{

3DModel model = Create3DModel("Robot.mesh"); //Get access to an existing 3D model

Use3DModel(model); // Now, the 3D model represents the entity

mVelocity = 10; //Velocity is an entity private variable

}



//Game Entity Update

void EntityUpdate()

{

pose.posX += mVelocity*timeTick; //Moves along X ( timetick is updated by game engine pose is a public variable of the entity that is read by the engine)

}


none
 
Comment: