Creating the player: an introduction to ECS systems, part 1

With the basics of components covered, let's turn our attention to systems. Systems are responsible for the logic of your game. In a way, you can think of them as entity processors because, most of the time, they take a set of entities as their input and produce a particular result as their output.

The first system we are writing is the one responsible for creating the player entity in our world, which we name, unsurprisingly, PlayerCreationSystem. It is defined as follows:

ECS systems derive from the SystemBase class, defined in the Unity.Entities namespace. When defining a SystemBase, you need to override its OnUpdate method. In this case, with the card creation system being used for bootstrapping purposes only and with no other work to perform on a per-frame basis, the body of the update method is empty. In addition to OnUpdate, you may also override the OnCreate and OnDestroy methods, which are invoked when the system is created and destroyed respectively.

All systems run in a system group and Unity provides three default groups: initialization, simulation and presentation, that are updated in that order. By default, all systems run in the simulation group, but here we explicitly show how you can define the system group by using the UpdateInGroup attribute. You can define your own system groups, but it will not be necessary for this course. System groups become essential for managing the complexity of bigger projects.

All entities live inside a world and you can create more than one world in your game; for our purposes, it will be enough to use the default world, which is created automatically. The entity manager, which all systems store a reference to in EntityManager, is your entry point to all the entity-related functionality provided by the ECS (creation and destruction of entities, addition and removal of components to/from entities, etc.). We create the entity by calling the entity manager's CreateEntity method and set its PlayerData component via the SetComponentData method. Note how, rather than hardcoding the player's health value in this file, we use an auxiliary utility class named GameplayConstants:

If you are wondering why the maximum player HP is not a constant, it is because it can be modified by an ability card; we will cover special cards later in the course.

Finally, with this system being used exclusively for bootstrapping purposes, we disable it right after creating the player entity by setting its Enabled property to false. There is no faster code than that which does not run!