sschmid / Entitas

Entitas is a super fast Entity Component System (ECS) Framework specifically made for C# and Unity
MIT License
7.09k stars 1.11k forks source link

AnyOf Collector/Trigger #881

Closed laughsuggestion closed 5 years ago

laughsuggestion commented 5 years ago

Hi,

So I've read in multiple places that the AnyOf semantics "work" but do not work as one might expect:

https://github.com/sschmid/Entitas-CSharp/issues/467 https://github.com/sschmid/Entitas-CSharp/issues/378

For me, I just need a "did anything change with these components?" system. So this is a snippet I am using for now:

    public static ICollector<TEntity> AnyChange<TContext, TEntity>(this TContext context, params IMatcher<TEntity>[] matchers)
        where TContext : class, IContext<TEntity>
        where TEntity : class, IEntity
    {
        return new Collector<TEntity>(
            matchers.Select(m => context.GetGroup(m)).ToArray(), 
            matchers.Select(_ => GroupEvent.AddedOrRemoved).ToArray());
    }

Usage:

        protected override ICollector<GameEntity> GetTrigger(IContext<GameEntity> context)
        {
            return context.AnyChange(GameMatcher.Hovered, GameMatcher.Selected);
        }

If there's something like this that already exists, or if you have know of a better pattern I'd love to hear about it.

PopRene commented 5 years ago

Undocumented, but will work (more or less the same, but not generic like your solution):

 protected override ICollector<GameEntity> GetTrigger(IContext<GameEntity> context)
 {
     return new Collector<GameEntity>(
         new [] {
             context.GetGroup(GameMatcher.A),
             context.GetGroup(GameMatcher.B),
         },
         new [] {
             GroupEvent.Added,
             GroupEvent.Added,
         }
     );
 }
akoolenbourke commented 5 years ago

Could someone please explain why AnyOf(A,B) doesn't work. I read this post but it's not clear to me.

If the collector is a group underneath then the group will populate with members that have ANY of those A or B added/changed right? Which is what is expected.

I just want a reactive system that will run whenever ether component A is added/changed OR component B is added/changed. I can do further logic in execute.

Thanks

laughsuggestion commented 5 years ago

Could someone please explain why AnyOf(A,B) doesn't work. I read this post but it's not clear to me. ...

@akoolenbourke Collectors collect and don’t release unless told to. So here’s what that means for our case:

Let’s say we have an empty collector for A|B called C. Let’s say A changes on entity E. The trigger matches, C does not already have E, so C collects E and the reactive system runs. Let’s say B is added to E. The trigger matches, C already has E in its collection, so the reactive system does not run.

This behavior is what is meant that the Reactive systems “work” but not as expected.

Sent with GitHawk

c0ffeeartc commented 5 years ago

@akoolenbourke

Could someone please explain why AnyOf(A,B) doesn't work. I read this post but it's not clear to me.

Here is how I understand it. Groups trigger on entity entering/leaving group. Once entity is inside a group, in order to retrigger entering it should first leave the group.

If the collector is a group underneath then the group will populate with members that have ANY of those A or B added/changed right? Which is what is expected.

Collector is collection of groups. If you need to trigger on each component, then you need more than one group.

I just want a reactive system that will run whenever ether component A is added/changed OR component B is added/changed. I can do further logic in execute.

Code examples above show how it's possible

akoolenbourke commented 5 years ago

@laughsuggestion

My understanding is that the collectors are cleared after processing so they can collect again. This is the way they can check for changes (not just adds).

Is the act of adding a component change handler done when an item is added to a group? That would explain it.

Component A is added, entity goes in group - change collection is hooked to that component. Component B is added, already in group change collection doesn't get hooked

laughsuggestion commented 5 years ago

@laughsuggestion ...

@akoolenbourke I’m not sure. I’ve not looked at the source for this.

Sent with GitHawk