Creating a component-based game (Part IV: Blueprints)

Right now we’ve got a player character in our game who can shoot some bullets out of his weapon. Both the player and the bullets were defined in the LevelSystem, defining their components and settings hard-coded.

This is surely not what we want for a bigger game where a game designer should be able to adjust the settings without the help of a programmer and where we don’t want to recompile the game each time we change the values.

This example uses an older version of the Slash Framework which can be downloaded here and is in the branch examples/kill-stuff of the repository. If you want to follow the examples step-by-step make sure to use those older versions. If you are already familiar with the framework you may be able to adjust the code to fit the current version of the framework.

Introducing blueprints

That’s why we use a data-driven approach with so-called blueprints for our games. As the name suggests, blueprints are templates for the concrete entities. You can think of them also as the classes you would have at the end of the inheritance tree in an object-oriented architecture. Some concrete examples would be: Player, Projectile, Weapon, Tank,…

In our component-based world, those blueprints are not code though, but pure data. They define two things:

  • Components that an entity created with this blueprint will have
  • Default values for the component attributes

Each blueprint is identified by a unique blueprint id, a simple string. This way a system only has to know the identifier of a blueprint to instantiate an entity for it.

Making our game data driven

If you have a look at the current state of our code, you’ll see that we already use blueprints in the LevelSystem for the player and the projectiles. But they are still defined in code, so let’s change that.

After importing our Slash.Unity.Common.Editor library, you’ll have access to an editor which lets you create and modify the blueprints that can be used in the game. Just choose the menu item “Slash Games/Blueprints/Blueprint Editor”. A new Xml file will be created which contains your blueprint definitions and a window will open:

Blueprint Editor
Blueprint Editor – Empty project

Here we can start to add a new blueprint for our player character. Just type the identifier into the input field on the left of the editor window and press the “+” button:

Blueprint Editor - Adding a player blueprint
Blueprint Editor – Adding a player blueprint

Now you can select the created blueprint and you will see the available components on the right. Let’s add the required components that we already set in code:

  • TransformComponent
  • MovementComponent
  • InputComponent
  • WeaponComponent
  • AnchorComponent
  • VisualizationComponent

As you add components, you’ll see that the attributes for each one are shown below the component list. Here you can set the default value for each attribute.

Blueprint Editor - Full configured Player blueprint
Blueprint Editor – Full configured Player blueprint

The editing should be easy enough, so even a non-programmer can understand how to set up and modify the values. Flagging the components and component attributes in your code with attributes will allow the editor to find them dynamically via reflection. So editing the blueprints comes almost for free!

We can add a blueprint for the projectile in the same way and are done with the data-side.

Blueprint Editor - Full configured Projectile blueprint
Blueprint Editor – Full configured Projectile blueprint

The data is stored in a readable Xml format, so you can also edit it there directly without using the editor. Although your designers may like a visual tool much better 😉

This was the data side, let’s see which adjustments we have to make to the code now.

Using the blueprints in code

The player character and the projectile definitions were created in the LevelSystem up to now. As we defined them in data, we can throw out those hard-coded definitions. All we have to know is the id of the player character that we instantiate at the start of the game:

The setup of the property may seem familiar: It uses the same tools as the components do with their attributes. Systems can also be configured from the outside via a game configuration. Additionally to the single inspector properties the game system needs to have the InspectorType attribute as well, so the class is considered when looking for inspector properties:

Just add the GameConfigurationBehaviour to a game object, e.g. the one where the GameBehaviour is located. You can now reference it in the GameBehaviour, so the game configuration is loaded and used for the game.

Game Configuration - Setting it up in Unity
Game Configuration – Setting it up in Unity

It will load the blueprints it finds at the specified resource path (whole project by default) and the game configuration and setup the game with those. The attributes of the game configuration are also shown in the inspector, e.g. our added LevelSystem.PlayerBlueprintId attribute.

So, do we have to add more than the attribute for the LevelSystem? Not really, but we have to delete some lines! Remember our former code for the instantiation of the player character?

Now that we outsourced the configuration to the Xml file this is replaced by:

Much cleaner, isn’t it? The EntityManager has a reference to the BlueprintManager of the game, so it will just look up the blueprint to use via the specified identifier. The BlueprintManager itself was initialized from the Xml data file.

Now you don’t have to change a single bit of code to modify your player character of the projectiles he shoots. Just change the data values for:

  • Movement speed
  • Maximum and initial bullet count
  • Initial player position
  • Prefab used for visualization of player/projectile

Conclusion

The blueprint system is an essential part of our framework. It allows to move the definitions of our entities outside the code. The main advantage is that no programmer is needed to adjust the configuration of the entities in the game and the game doesn’t have to be recompiled if a value changes.

The editor comes almost for free, as it finds all available components via reflection and shows the correct controls depending on the defined data type. Although the data is stored in a readable and editable Xml format, a visual editor makes life even easier and allows less error-prone editing.

The blueprints give the whole power of a component-based framework into the hands of the designers. After a bit of development you may already have most of the functionality in your game. Game designers tend to come up with ideas to recombine abilities of different entities:

“Hey, it already works in the game, so it shouldn’t be difficult to give this ability to a tree!”

And indeed, with a component-based framework this isn’t a problem. With the data-driven approach though, you can answer now:

“Sure, just start your blueprint editor and drag component XYZ on to the tree blueprint.”

So where do you store your game configuration? Do you have similar systems that allow configuring the features of your game easily? I’m always curious about more ways of making programmer’s life easier by delegating the work to other members of the team 😉