Component-based Entity Systems: Project Setup

In the last two posts I talked about data binding and an asset called Data Bind for Unity I created to use it with Unity. There are more important things in a game than a clean separation between logic and presentation though. But when we started our last work-for-hire project, I realized that our foundation for the game logic was already in a very complete state, so I could concentrate on other parts of the architecture.

At Slash Games Nick and I created a framework (called “Slash Framework” of course 😉 ) which we could use for a wide range of projects. The framework is based on an approach called Component-based Entity Systems or CBES.

There are quite a few great sources to learn about the basics of CBES. So I won’t bore you with the details and give you the links instead:

If you are completely new to this architecture, make sure to read a lot of articles about it to get the whole picture. You don’t have to take one approach to implement the architecture completely, but rather take the things you feel comfortable with first and build up slowly.

Our framework grew for the last 2-3 years and we made quite a few changes to it during that time. Nobody writes a perfect architecture from scratch 🙂

In this post I like to focus on how we set up our projects with component-based entity systems to keep in control of the growing complexity during development.

Structure a project with CBES

We participate in game jams regularly and in one last year I wanted to keep it simple and don’t use our framework which was quite big already. Very quickly it was clear that this was a mistake. Even small projects tend to become very messy very quickly. You always need a bit of structure, especially if you work in a team.

Component-based entity systems push you towards a clean structure with several advantages:

  • You know where to put your code, so you can concentrate how a feature is implemented instead of thinking about the architecture
  • Everybody else on your team (and yourself after a couple of days) knows where to find what. That makes bug fixing easier as well.
  • During the development of a game, more and more features are added. CBES can be structured in a feature-oriented way. So most of the time you start a new feature task, you can start with some new classes especially for that feature. This prevents the introduction of bugs into existing features when adding a new one.
  • Working in a team is far more safe from merging conflicts. Most of the time each team member works on one feature and as those features are located in their own classes, interferences are very minor.

Adding a new feature

When you start with a new feature of your game, you’ll have different parts to add:

  • Data
  • Logic
  • Events

The data of a feature contains configuration data, e.g. initial and maximum health points, and runtime data, e.g. current health points.

The logic is what changes the runtime data and makes the feature work as it should.

The events are used to communicate with other features and with the presentation of your game.

These parts map really well to CBES: Data goes into components, logic is done in a system and events are added by an event enum and event data classes.

So our current approach of a clean folder/namespace structure looks like this:

  •  Features
    • Feature A
      • Components
      • Events
      • Systems
    • Feature B
      • Components
      • Events
      • Systems
    • Feature C

There are still some things which I don’t like, e.g. where to put components that are used for multiple features. But I hope that a clean solution will come to my mind soon.

When you start a new one you begin to think about which data is involved and add one or more components to hold it. You can often start with one component if you are not sure, as refactoring a component isn’t much work.

After that you typically create a new system. This system works on the component(s) you just created. Either it changes the data of those components regularly in the Update method. Or it does so on events.

Those events may come from other features, but it’s pretty likely that you’ll need some specific events for the feature as well. There is a specific type of event which we separate from the normal ones: Actions are events which are send to the system from outside to indicate that a specific actions is desired (e.g. FireAction). So we typically have two event enums: FeatureAction and FeatureEvent.

Keeping features separated

If you are done with a feature, you are done with it completely most of the time. If nothing changes from a game design perspective (and you didn’t write any bugs, of course), you don’t have to touch it again. This is really a nice way to work as you can be sure that no new bugs are introduced into that code.

Starting a new feature is almost as starting a new project. You start from scratch with some new classes that have well-defined responsibilities. This lets you concentrate completely on the implementation of the new feature.

The event driven way CBES work is the key to this workflow. It also allows for easy refactoring. So if one of your systems of components grows too big, just split them in a way it makes sense.

Fun fact: The features are so separated that we often use the Unity physics for collision detection for small projects. We could do it in an own PhysicsSystem but the other features really don’t care about it. All they require is the events when a collision occurred.

Conclusion

CBES is a nice architecture because it lets you split your game into a bunch of features and keep those really separated. This makes it easy to keep the growing complexity of your project under control. Features can be added, removed, reworked, (unit) tested,… all on their own without the risk of influencing other features.

As games are living creatures which tend to change quite a lot in the course of the development, CBES feel like the best solution for me to stay flexible and structured at the same time. You can check out a early version of our framework, but if you are really interested in the current version, just send me a mail. We plan to release it this year and could use some fresh pairs of eyes to see if it works for other developers as well as it does for us.

There is always room for improvement. So, do you have any good techniques that you already used successfully with CBES? Let me know in the comments!

8 thoughts on “Component-based Entity Systems: Project Setup”

  1. Really enjoying reading this series of blog posts. Still looking for a framework I feel work well for unity (professionally I make business apps, where I’m used to mvvm or mvc). I’ve used other frameworks/libs, like uframe, strangeioc and unirx, and they all have certain attractions but fall short for me. Looking forward to giving this a spin – and just bought your databind asset as a thank you for the articles. Will probably be useful as well, so a win-win :-).

    1. Hi Ronnie!

      Thanks for the purchase 🙂 Let me know what you think about it and if you’ve got any issues with it. I’m always open for feedback and like to improve/extend the asset further over time.

      We will release our main framework soon, just have to get some work out of the way and gather some motivation and courage for this step. Although it is very game focused you might check it out 🙂

      Cheers
      Christian

  2. can CBES you guys builded support simulate the game system’s running framerate?
    Because I think system control of all the entities. System should quick check the one battle result in one function simulate call.

    1. Hi Chiuan!

      Sorry for the late response, just saw and approved your comment 🙂

      Your game logic shouldn’t depend on the game’s frame rate, but should do its calculations either completely event driven if possible. Or with a fixed frame rate.

      You can simulate a fixed frame rate inside the system itself by accumulating the time until it reaches your desired frame time. You do a fixed update than and subtract the frame time from your accumulated time.
      If you need a fixed tick for multiple systems you can also create a system which does this accumulation and sends out a Tick event each time a fixed update should be performed.

      Hope that helps and I understood your question correctly. If not feel free to reply 🙂

      Cheers
      Christian

  3. Hi Christian,

    I’ve been reading extensively about CBES on your blog and everywhere on the internet. I am also very interested in using your framework, which I admire. If I may, I have a few questions that’ll set me on the right path:

    I’ve read about all the benefits of CBES, but how much of a difference would CBES make for a small game (Think “Ant Smasher”, https://goo.gl/HM2cNW) compared to using Unity’s component model as it is?

    Given that I’m a programming & Unity3D newbie, I’m thinking of using Unity as it is for my first (small) game, and then learn to use your CBES framework for my games after that. That way, I can:
    1) Get my first game out faster. It’d probably take me a while to learn to use your framework, given my beginner level.
    2) I can experience first hand (I’ve only read about them so far) the issues that CBES solves. Then, when I use CBES after my first game, I will be more aware of its strengths, which will allow me to learn it more efficiently, and apply it more effectively.
    Would you recommend this path of action, or do you have arguments that would invalidate my way of thinking?

    1. Hi Adrien,
      Sorry for the really late reply. I thought I would get a mail when a comment arrives, but something was broken.

      About the differences between using CBES and Unity’s system: It always depends on the project. If you have to prototype some really rough, small game really quickly, e.g. at a game jam, you shouldn’t use a big framework if you have never used it before. There is always a bit of overhead and complexity added, unfortunately nothing comes for free 😉
      But if you have the time a small project is a really good opportunity to learn a new framework. You really get a feeling for the extra stuff you have to put in to use the framework, but also about the advantages it gives you, even in a small project (e.g. configuration, serialization, logging,…)

      On the other side you write that you are also new to Unity. In that case you probably will anyway learn a lot of new stuff about the engine. Adding more complexity with an additional framework might be too much than. Guess you should start small and than add the framework if you feel you can handle it 🙂

      Feel free to comment or send me a mail directly, hope my answer still helps although months too late 😉

  4. Thanks for all the great info in the blog! I’m reading up on frameworks for CBES and it’s not obvious why I’d choose one over another (or more than one.) For example, how would you compare your SlashFramework to Entitas (or some of the other common frameworks?)

    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *