Simple Example

Overview

This Tutorial will show you some of the basics of setting up and using the ECS framework. In this simple example, we will be creating a Sprite that will move across the screen.

Project Setup

You can download gs-ecs-simple.zip a startup project to get you started. It contains the ECS framework, and the Logging system it needs. The startup project was created with Godot 3.2, but anything after that should work as well, with the exception of 4.0

You may also clone the project and open it that way.

$ git clone https://gitlab.com/godot-stuff/gs-ecs-simple.git

Note

Godot 4.0 was still in early development when this Tutorial was written. It will be updated when it is released and the ECS has been modified to work with the new version of Godot.

Entity

The first thing we are going to do is add an Entity to the project. We need to choose a root node for the player object. As a general rule, a scene’s root node should reflect the object’s desired functionality - what the object is. Click the “Other Node” button and add an Area2D node to the scene.

_images/add_node.png

Godot will display a warning icon next to the node in the scene tree. You can ignore it for now. We will address it later.

With Area2D we can detect objects that overlap or run into the player. Change the node’s name to Entity by double-clicking on it. Now that we’ve set the scene’s root node, we can add additional nodes to give it more functionality.

Before we add any children to the Entity node, we want to make sure we don’t accidentally move or resize them by clicking on them. Select the node and click the icon to the right of the lock; its tooltip says “Makes sure the object’s children are not selectable.”

_images/lock_children.png

Let’s add the entity.gd script to the Node we just created. This script contains some boilerplate code to add this scene as an entity. Look here for more information on Entity.

_images/add_entity_script.gif

Save the scene and call it entity.tscn. Click Scene -> Save, or press Ctrl + S on Windows/Linux or Cmd + S on macOS.

With that, let’s run the scene and see what shows up in the log. Press F6 to run the scene, and your log should look similar to this.

** Console Appender Initialized **

TRACE      1        [entity] _init
TRACE      2        [entity] on_init
TRACE      3        [entity] _ready
TRACE      4        [ECS] add_entity
TRACE      5        [ECS] has_entity
TRACE      6        [entity] on_before_add
DEBUG      7        - entity [Area2D:1187]:Entity has been added
TRACE      8        [entity] on_after_add
WARN       9        No Components found
TRACE      10       [entity] on_ready
TRACE      11       [ECS] _exit_tree

The key message to look for is that the Area2D has been added to the framework.

Let’s add a component to our Entity now.

Component

The data for your Entities are stored in Components. In the ECS Framework, we usually create Components visually by creating an empty node, and adding a script that subclasses the component.gd script.

To prepare our Entity to find the components we add, we need to create an empty Node called Components first, and then you can add your components to that node. When your project starts, any Component attached to that parent Node will be added as Component.

This is how your Entity should look.

_images/entity_with_component_node.png

Now let’s create a new Scene, then add a new Node and rename it to Velocity.

Save this scene with the name “velocity.tscn”, and then attach a new Script to the Node and call it “velocity.gd”.

Velocity needs both a direction, and speed so lets modify our Script to include those, and expose them as parameters for the Component itself.

class_name Velocity
extends Component

export var speed : float = 100.0
export var direction : Vector2 = Vector2.RIGHT

So now we have a component that will travel at 100 pixels/second in the Right direction. Notice that there is no game logic at all in this Code. That will come later when we talk about Systems.

Save the Velocity Component, and then open up the Entity Scene again.

Now you can drag the Velocity Component you just created onto the “Components” Node in your Entity.

_images/add_component_to_entity.gif

Now when we press F6 to run the Entity Scene again, the output should now show us that a new Component called “velocity” was registered and added to the entity.

** Console Appender Initialized **

TRACE      1        [entity] _init
TRACE      2        [entity] on_init
TRACE      3        [entity] _ready
TRACE      4        [ECS] add_entity
TRACE      5        [ECS] has_entity
TRACE      6        [entity] on_before_add
DEBUG      7        - entity [Area2D:1192]:Entity has been added
TRACE      8        [entity] on_after_add
TRACE      9        [ECS] entity_add_component
TRACE      10       [ECS] has_entity
TRACE      11       [ECS] has_component
TRACE      12       [ECS] add_component
DEBUG      13       - new component velocity was registered
DEBUG      14       - added velocity component for entity [Area2D:1192]:Entity
TRACE      15       [entity] on_ready
TRACE      16       [ECS] _exit_tree

System

Systems are the parts of your game that contain the logic to make things go. For our example, we want to create a system that will Move anything that has a Velocity Component attached to it.

To do this, let’s create a new Scene and add a Node, and call it “VelocitySystem”. Save the Scene as “velocity_system.tscn”, and then attach a new Script called “velocity_system.gd” to it. Replace the Code for the Script with this.

class_name VelocitySystem
extends System

func on_process_entity(entity : Entity, delta: float):
    var _component = entity.get_component("velocity") as Velocity
    entity.position += _component.direction * _component.speed * delta

Because we are subclassing the System class, we get some inherited methods. The one shown here is called “on_process_entity”. This method is called for every Entity registered that has a Component matching the list of Components for a System.

The other two important areas in this example are the reference to the Velocity component using the get_component method on the Entity Scene. When you use this method, it pulls the reference of that Component from memory in the ECS framework, not from your Scene itself. It then uses those values to calculate the new position of the Entity. You can update values in a Component, just like you would any other Script.

Now when we press F6 to run this Scene, we should get output similar to the following.

** Console Appender Initialized **

TRACE      1        [ECS] add_system
TRACE      2        [ECS] has_system
TRACE      3        [system] on_before_add
DEBUG      4        - system velocitysystem has been added
TRACE      5        [system] on_after_added
TRACE      6        [ECS] _exit_tree

Before we go to the next step, let’s make sure that we mark this System to handle all Entities that have a Velocity Component.

To do this, Select the Root node of your System, and you will notice that there are a few properties. The first, called Components, lets you enter in a list of Component names, separated by commas, that will be processed by this System.

_images/system_properties.png

The next two properties, should be left to the default of “enabled”. These two properties are used to Activate the System, and force the System to start running immediately when the Scene starts.

Putting It All Together

Now it is time to put everything together.

Create a new Scene with a new Node called “SimpleEcs”. Now, drag the Entity and VelocitySystem Scenes onto your new Scene. It should look like this when you are done.

_images/simple_scene.png

Save your Scene as “simple_ecs.tscn” and then add a new Script called “simple_ecs.gd” to it. Replace the code with this instead.

extends Node

func _process(delta):
    ECS.update()

Save your Scene, and press F6 to run it. You should see the Godot sprite move across the Scene. That’s it, really it is that simple. Calling the update function will take care of everything.

_images/simple_ecs.gif

Congratulations

Awesome! You now know some of the key concepts on how to use this simple ECS Framework for the Godot game engine. We are working on more Tutorials and Guides to help you get started, and to show you more advanced techniques when working with it.

Download some of the Demos available to see what else you can do with this simple ECS Framework.