Need some insight on my ECS implementation

I need some insight/recommendations on the way my entity component system is implemented. I think I might be doing something wrong because my systems depend on each other (which gives me bad coupling).

In order to describe my implementation, I’ll give an example of how I would create an entity with an asset. First off, I create an entity and I add a ModelComponent to it, which contains the path to the asset (as a String). Then, my ModelSystem takes this entity, gets the component, and loads the asset using the path in the component. I then store the asset that was just loaded inside a map, using the ID of the entity as a key.

Now lets say I need to access the spatial from another system, such as the AnimationSystem, I use ModelSystem.get().getEntityModel(entityID) (because currently each system is a Singleton). This is whats been bugging me about my implementation: how would I share things between my systems that shouldn’t be inside components (such as a spatial) while having minimum coupling.

Whats the best/right way to do it?

That’s a pretty common approach… though in general singletons are bad here. You should use app states. If you extend BaseAppState you can even trivially get your sibling app states.

View ‘systems’ like this are often going to have to coordinate. It’s just the nature of things. They aren’t following the real ‘system’ pattern anyway as they are often strictly views.

Like any layered architecture, it is ok to have some core systems upon which the others depend. Like any layered architecture, you will be happiest when you keep this to a minimum. For example, having a SoundSystem and an AnimationSystem depend on a general ModelSystem is fine. Try to avoid further cross contamination like SoundSystem and AnimationSystem interaction if you want to maintain some flexibility. (It’s also a potential bad smell.)

You really should use app states over singletons, though. You will get a ton of life cycle benefits and some other flexibility.

I’ve solved this by naming the models with its entity id in the visual system (similar to your model system I guess)I then can question the model holiding node (for example the root node) to give me a model of an entity to get the animation control to start/stop an animation in my animation system.

Ok, thanks for the info. I’ll look into using app states instead of singletons like you suggested.

Ya that sounds similar to my implementation with the exception that you don’t keep your models in a map, you just ask the root node for the models through a system.

The map will be faster and ultimately provides more flexibility.

I’ve always felt the looking up spatials by name is very fragile.

So you expose the visible

Map<EntityId, Spatial> models;

to other system which decorate your models with running animation for example? And all spatial related system are anyway in the same thread else you can run into those nasty errors while two threads try to change the scene graph…

Ok I think I will do it the same way, it even seems faster :slight_smile:

On the visual side (the only place that would need access to the Spatial) everything is already on the render thread.

And I don’t expose the map directly, I put a getModel() method on the app state. That way if I reorganize my scene graph, move things into zones, whatever, the other states don’t care. So long as I give them the answer they want.

1 Like