libgdx / ashley

A Java entity system inspired by Ash & Artemis.
Apache License 2.0
875 stars 144 forks source link

Different systems with the same family filter receive different entities. #293

Closed ZumiKua closed 4 years ago

ZumiKua commented 4 years ago
package in.zumikua.stg;

import com.badlogic.ashley.core.*;
import com.badlogic.ashley.utils.ImmutableArray;

public class Test {

    static public void main(String[] args) {
        Engine engine = new Engine();
        engine.addSystem(new SystemAddEntity());
        engine.addSystem(new SystemAttachComponent());
        engine.addSystem(new SystemC());
        engine.update(1);
    }

    static class A implements Component {

    }

    static class B implements Component {

    }

    static class SystemAddEntity extends EntitySystem {

        SystemAddEntity() {
            super(0);
        }

        boolean added = false;
        @Override
        public void update(float deltaTime) {
            super.update(deltaTime);
            if(!added) {
                getEngine().addEntity(new Entity().add(new A()));
                added = true;
            }
        }
    }

    static class SystemAttachComponent extends EntitySystem implements EntityListener {

        private ImmutableArray<Entity> entities;

        SystemAttachComponent() {
            super(1);
        }

        @Override
        public void addedToEngine(Engine engine) {
            super.addedToEngine(engine);
            engine.addEntityListener(Family.all(A.class).exclude(B.class).get(), this);
            entities = engine.getEntitiesFor(Family.all(A.class, B.class).get());
        }

        @Override
        public void update(float deltaTime) {
            super.update(deltaTime);
            System.out.println("SystemAttachComponent " + entities.size()); // outputs 0
        }

        @Override
        public void entityAdded(Entity entity) {
            entity.add(new B());
        }

        @Override
        public void entityRemoved(Entity entity) {

        }
    }

    static class SystemC extends EntitySystem {
        private ImmutableArray<Entity> entities;

        SystemC() {
            super(2);
        }

        @Override
        public void addedToEngine(Engine engine) {
            super.addedToEngine(engine);
            entities = engine.getEntitiesFor(Family.all(A.class, B.class).get());
        }

        @Override
        public void update(float deltaTime) {
            super.update(deltaTime);
            System.out.println("SystemC " + entities.size());  //outputs 1
        }
    }
}

With the above code, SystemAttachComponent receives zero entities, but SystemC receives one entity, is this a bug or an intended behavior?

metaphore commented 4 years ago

The example code actually outputs

SystemAttachComponent 1
SystemC 1

I'm not exactly sure how the example should demonstrate the described problem, but I definitely see a mistake in the usage of engine.getEntitiesFor(). From the method's javadoc:

Returns immutable collection of entities for the specified {@link Family}. Will return the same instance every time.

You shouldn't keep the reference to the returned collection, but instead, persist the result using your own instance.

mgsx-dev commented 4 years ago

@metaphore it actually returns the same instance for a given Family filter, it's the typical usage, just like in IteratingSystem.

@ZumiKua and @metaphore which versions are you testing this code against? my guess is it's fixed in master branch.

metaphore commented 4 years ago

@mgsx-dev doh, I should really dig deeper than javadocs haha. Thanks for pointing out. Hard to tell which commit I'm on, I'm using 1.7.4-SNAPSHOT.

mgsx-dev commented 4 years ago

i can confirm it's fixed, @ZumiKua you can use either 1.7.4-SNAPSHOT or jitpack: "com.github.libgdx:ashley:master-SNAPSHOT"

mgsx-dev commented 4 years ago

@metaphore i'll improve the javadoc, it's a bit confusing indeed :-)

ZumiKua commented 4 years ago

Sorry for my late reply, I'm using 1.7.3, which is bundled with the newest(I guess) gdx-setup. Maybe gdx-setup needs to be updated? Anyway, thanks for your help ❤️