Advertisement

ECS creating systems based on entity or components?

Started by February 06, 2024 05:57 PM
8 comments, last by alice wolfraider 9 months, 1 week ago

TL;DR: Should I have distinct components such as PlayerController and CameraController that would act as a “brain” this would tie/couple systems to an entity. Or make systems that update components and systems that act on the updated components this way systems aren't (or shouldn't) be tied to a specific entity.

So I'm a little confused on how to make systems in ECS it feels like I'm trying to make systems based on the entity rather than the components which leaves me with some systems being niche I guess? In my game engine project when it comes to input I have a global input manager (a singleton?) which is not part of the ECS then I created a PlayerController and CameraController which uses the input manager like this:

class  CameraController : public ISystem {
public:
	void Update(float timestep) override {
		// Mouse Input
		if (gInputManager.IsMouseButtonDown(SDL_BUTTON_RIGHT)) {

		}

		// Keyboard Input
		if (gInputManager.IsKeyDown(SDLK_w)) {
		}

		if (gInputManager.IsKeyDown(SDLK_s)) {
		}
	}
};

class  PlayerController : public ISystem {
public:
	void Update(float timestep) override {
		

		// Keyboard Input
		if (gInputManager.IsKeyDown(SDLK_w)) {
		}

		if (gInputManager.IsKeyDown(SDLK_s)) {
		}

		// Jump
		if (gInputManager.IsKeyDown(SDLK_SPACE)) {
		}

		// Some ability
		if (gInputManager.IsKeyDown(SDLK_e)) {
		}
	}
};

So, these systems are only useful to a single type of entity, and I feel like that might be the opposite of what ECS is trying to accomplish? Something I've seen frequently is to have some sort of input component I don't actually know how this would work, but if I had to take a stab the idea seems to be you'd have one system that updates your input component and then any entity that needs input uses that component and then I'd have like a mover system that uses the input component to move the entity so now instead of having a system targeting a specific entity like the camera or player I have two general purpose systems that can handle movement for any entity that uses input. This raises a few questions though like being able to look around with the camera or the player being able to activate abilities these are specific or handled differently by some entities which I think is why I went with my original code.

So, I'm curious of both methods mentioned are valid or if one is more typical than the other?

You seem to confuse two components (very similar or the same) that are owned by, and control movement of, entities of type “player” (actually, I presume, fairly generic characters) or of type “camera”, with two systems that both collect mouse and keyboard input once per frame (with different rules) and set the state of those input-driven movement controllers.

Actual movement actions should occur at a later stage, with these input-driven controller obeying the previously collected input and other controllers (e.g. an enemy AI that tries to take cover) deciding movement in other ways.

Having only one player character and one camera is not an excuse to derail and complicate the overall architecture: there is a certain behaviour, and its place is a system for central control and a component for entity-specific data even if the entities are singletons.

Omae Wa Mou Shindeiru

Advertisement

I would also add that it's essential not to get pulled down into the weeds about whether it's related to one entity, as that can easily change.

In my game, I have a CameraSystem and it is responsible for managing multiple camera controller types. We have controllers that render sub-viewport / sub-scenes for minimaps and animated character portraits for health frames. We have a combination of orbital controllers for the player when they're out in the main world and then a series of different types of camera controllers that are swapped in and out based on certain world actions, such as interacting with a specific mini-game or quest in the world. We also have camera controllers for handling cinematic camera tracks for when we play world-based cinematics, and the list continues.

For the PlayerController, we have a system designed to manage a variety of “EntityControllers” that support AI movement, player movement, and various physics bodies like elevators. We even have a specialized controller for when the player casts “Mind Control” on a target, and this controller is limited in that the player can do a subset of actions with the controlled character, but not everything as they can with their actual character.

You may not need all this fancy stuff at the outset, typically most early games don't, but that's the beauty of a framework like ECS is that it makes it tremendously easy to add, augment, and replace prior iterations as long as you design entities, components, and systems with well-defined contracts and boundaries.

Konjointed said:
So I'm a little confused on how to make systems in ECS it feels like I'm trying to make systems based on the entity rather than the components which leaves me with some systems being niche I guess? In my game engine project when it comes to input I have a global input manager (a singleton?) which is not part of the ECS then I created a PlayerController and CameraController which uses the input manager like this:

IMHO, what you have shown in your code should not, in an of itself, be part of the ECS. My engine uses ECS as the primary “glue” between low-level system and high-level logic; but I've come to the conclusion that coding specific gameplay-logic in ECS is not the best use of the pattern.

What you have shown are, as the name suggests, “controllers”. They are not systems. Trying to make them ECS-systems is forcing something unto a pattern that doesn't naturally fit. Your both scripts should be “controllers”, or “behaviours”, that you can attach to an entity, or component, to control them. Your ECS should only model what a “camera” intrinsically represents (that is, a view into the world with specific properties, but also reusing the transform that an entity might have). It doesn't care what happens when “W” is pressed. Your behaviour/controller dictates that. That way, the ECS/system itself is actually not coupled to a single thing - the camera-system only processes specific camera-properties, like view-matrices. That's the design I use for my 2d engine/game. There is a “Transform2D”-component, and a “Camera” component. CameraSystem uses transform+camera to calculate the view. Then, the actual player-controller (which is a regular, non-ecs script) implements the behaviour of the camera in regards to the player-movement. There can be many different ways to control these camera-entities/components; for cutscenes I can create external camera-entities and activate them/transition to them, to show camera-transitions…

That, IMHO, is the proper way to use ECS for your case. You get both the flexibility of the ECS, but don't have to misuse the pattern to fit what is essentially scripted behaviours.

@undefined If I'm understanding this correctly instead of the camera system controlling the camera I'd have a controller class that's not part of the ECS (or a script) to do that for me? I assume this updates the component and then the system just uses that updated information? Is this what hybrid ecs is?

Konjointed said:
@undefined If I'm understanding this correctly instead of the camera system controlling the camera I'd have a controller class that's not part of the ECS (or a script) to do that for me? I assume this updates the component and then the system just uses that updated information? Is this what hybrid ecs is?

Pretty much. The controller can be implement via ECS - in my case, I have a “script” compoment that is treated like a regular ECS component, that allows me to attach scripted interactions to entities.

I guess you could call it hybrid ECS, but I would call it “practical” ECS 🙂 For context, I develop a 2d oldschool action-RPG, which ATM has probably ~30 hours of story-driven gameplay/content. In such a case, using “systems" for behaviour is entirely unpractical. I don't want to make a different system every time I have a scripted NPC/Cutscene, for (hopefully) obvious reasons. In such a game, there are many scripted sequences that are entirely unique, and a regular behaviour-type script is much better suited for those. As you said, those behaviours use the ECS components and modifier their state, which then makes the systems process it accordingly.

In a smaller, less content-driven game, you might get away with using an ECS to implement behaviours like you shown. But I do firmly belive that it's suboptimal, and will not scale well.

Advertisement

I will explore this topic more deeply later

but you clearly rely too much on the toolkit inside the engine: since some tools (components) can be built-in assets and have other levers of influence on something: and the system gives some independence from variations - while also granting flexibility

[off-topic self-serving video link removed by moderator]

Alice Corp Ltd

alice wolfraider said:
I will explore this topic more deeply later

An empty promise to reply in depth later is not helpful. Tell us more about this:

alice wolfraider said:
rely too much on the toolkit inside the engine: since some tools (components) can be built-in assets and have other levers of influence on something: and the system gives some independence from variations - while also granting flexibility

-- Tom Sloper -- sloperama.com

entity system

components of Entity

components of System

Entity : "System of Components"

.. components entity system

combine | compuse

System of Entities

___________

no matter how much say it won’t be so clear

because it all starts with

Case of Choosing something : System of Choice

and then confusion happens: since the keys are not a choice

1 / 2 / 3 .. 21 : by selecting 1, a procedure (script) “Select 1” is created

The "pressed key" key can translate there to any choice from 1 .. 21

since in Logic, depending on the Situation in the Game, the choice can be different

___________

"Tag of Count" : any variable can contain a certain value 25 / 27 / 29

with a value of 25 we select option 1

with a value of 27 we select option 2

with a value of 29 we select option 3

that is, we send it wherever needed depending on the conditions

and if 25 is 25 variations but choice 1: that is, in the Case of Choice choice number one

.. and if it comes from the keys, then selecting from one key to one selection will not give any flexibility

___________

multivalues : multiselect

an object can have many scripts, but also many scripts can control different objects

Alice Corp Ltd

This topic is closed to new replies.

Advertisement