0
\$\begingroup\$

I'm trying to wrap my head around the concept of ECS (Entity Component System). I think I grasp the concept of the different parts, Entities, Components, and Systems.

Entities: Basically just a container for components

Components: Data. E.g Transform component holding position, rotation and scale.

System: Runs on a subset of entities matching a combination of components. E.g. RenderSystem rendering all entities with a Mesh and a Transform.

What I'm having trouble wrapping my head around is how a system is supposed to assign data regarding the surrounding environment to the components without using global data. And it's probably because of a lack of understanding.

Example of what I'm getting stuck on:

Lets say I have a Player entity consisting of, among others, a Transform component. And lets say that there are multiple Zombie entities roaming the game world, which has a Transform and a AIPathfinding component. So I would naturally create a System that operates on Transforms and AIPathfinding to make the zombies chase the player.

My only problem is, how is the system supposed to know where the player is, or if there even is a player within range, without having to grab the player globally? Sure I could pass the player into the creation of the system. But what if along with the player the zombie are also chasing a constantly changing amount of civilians. Do I pass them to the system at creation as well? Or should I have some global way to fetch entities matching a component query, similarly to how the system detemines which entities to operate on?

I understand that this might be entirely up to the implementation of the ECS. But I'm having a hard time finding resources that explains any further that the most basic systems (RenderSystem etc.).

\$\endgroup\$
  • 1
    \$\begingroup\$ Your proposed solutions both sound like they'd work. Have you run into any specific difficulty implementing either one? \$\endgroup\$ – DMGregory May 5 at 19:48
  • \$\begingroup\$ Not really. Wanted to check with people before I did something totally stupid :) I'm currently leaning towards the second solution I mentioned. However that will result in me needing to replace the ECS I'm using. \$\endgroup\$ – Mattias May 5 at 20:28
2
\$\begingroup\$

My solution to this would be to create a component AITarget which marks an entity as something zombies are supposed to attack (like a player or a civilian).

Now the ZombieAI system would receive not one but two separate sets of component-tuples. One for all entities with the Transform and AIPathfinding components and another set with the Transform and AITarget components. The job of the system would be to find the "best" AI Target for each zombie.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ It's too early to tell. But I think this approach will work the best for me. I'll have to either rework the ECS I'm using or write my own. But when that is done I think it will suit my use case. \$\endgroup\$ – Mattias May 7 at 16:51
  • \$\begingroup\$ Also the system should work ona given entity at a time, but while it's running for that one, should have access to the complete list of entities. so the system should be system.simulate(entity, entities), and then you will filter out the entities you need to target. for example AOE power that damages zombies and break walls? \$\endgroup\$ – Mg01 May 21 at 15:48
0
\$\begingroup\$

Entities: Basically just a container for components

Your entity, should only be an id. Usually an int. Not a pointer, but a handler. The ECS will associate components to that id, and will allow you to query them with some criteria returning a set of ids. This is important.


As usual, ECS lack spatial awareness. They are not the best tool if you want to collide nearby objects, query only the entities that would be visible in camera, or - in this case - find a path to a target.

If your ECS has support for events (attached component, removed component, updated component), you can work around this by keeping track of the positions and holding (ids of) entities in an auxiliary structure.

If your ECS does not have support for events, you can still do it. Attach a component to the entity that should trigger the event. A system picks it up, process it, and then removes it.

Another option is having an ECS that lets you set, on creation, custom containers for particular component kinds. This would allow you to define a custom structure to hold positional information, such that you can query it for locality or proximity.

Thus, you either set a custom container for positional components in the ECS, use an auxiliary structure keeping it in sync with the ECS, or don't store positional information in the ECS at all…

Either way, you really want some form of spatial structure. A grid, a quad-tree or oct-tree, a binary space partition tree… Those are the right tools.

For crowds chasing a target, I would strongly advice to use an Influence Map Pathfinding. The idea is that you will store an influence map, or rather I should say, you will store an influence value in each node of your spatial structure. And this value will represent distance to the target. Then, you query in what node of the spatial structure the current entity is, query the neighbors and that tells you in what direction to move it.

That means you do no need to call a path finding routine to find a path from each member of the crowd to the target. You only need to update the influence map as the target move. It is also possible to have multiple targets, then the influence value is the distance to the nearest.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.