Registering EntityProcessors


#1

After much dicking around I managed to get the Update method triggered on my

public class TileProcessor: EntityProcessor<TileComponent> {
    public override void Update(GameTime time) {}
}

Apparently if you add the following attribute to your EntityComponent it gets picked up automagically

[DefaultEntityComponentProcessor(typeof(TileProcessor))]
public class TileComponent : EntityComponent {}

Is there a way to explicitly add an EntityProcessor to the registry (EntityManager if I’m not mistaken)?
I feel the attribute is a bit against how you’re supposed to use the system, but maybe that’s because I’m still learning.

Once I get comfortable with how the ECS is implemented in Xenko, I would like to edit a few pages on the docs. This is a rather essential part of the engine that is, in my opinion, is rather under-documented :slight_smile:


#2

I looked a bit at the source code and it does seem pretty hard to tell where to register the processor with code.

One hacky but might-work idea: EntityManager uses reflection to grab the default processor attribute. That also means that you can probably register the default processor using reflection yourself and adding the attribute to that class at runtime, probably using CustomAttributeBuilder or something similar.

The only tricky part would be finding the right spot to add the attribute before that type gets processed by the EntityManager. Since you’re trying to do this with code anyways, you could just have a convention that those entities cannot be made until you know the attribute was added.

Not ideal I know, but hey it could also be a basis for a new pull request to the engine lol


#3

Glad you came to largely the same conclusions I did. Validates my ideas a bit :slight_smile:

If I’m making pull requests I would maybe go the same way as the services go.
Add them to a collection on Game, which would then be used by the EntityManager.

I Think that the consistency, together with a property that’s straight up called “game.EntityProcessors” would demystify this bit of essential magic maybe?


#4

What’s wrong with using an attribute? That’s a declarative way of doing dependency injection (or more specifically here “resolution”) that is quite elegant IMO.


#5

There’s nothing wrong with using attributes for injection. It’s definitely not my preference, but that’s not really relevant off course. The problem is that the dependency is currently defined twice and once the wrong way round.

If I understand correctly the component just holds data. To exist it needs nothing and nobody. It has no dependencies.
The processor requires one- or a set of components to function. It has a dependency on EntityComponent.
The attribute defines the dependency from component to processor.

Furthermore the dependency is already defined by this part:

MyProcessor: EntityProcessor<T> where T: EntityComponent

I’m still experimenting, but I think this will most clearly show itself when you have multiple processors requiring the same component.

As a second argument I would love to reduce the use of Activator.CreateInstance().
Processors don’t need to be serialized, so it would be nice if we could have actual constructors.

All of this is assuming I’m understanding the intent correctly off course.
I’m just going on what I’ve learned from other ECS systems and trying to make the pieces fit.