-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEATURE] Iterate over many aspects with less boilerplate code ? #614
Comments
The way we iterate definitely is verbose, but it is fast and avoids creating iterators or other objects. I personally favor less boiler plate myself and wouldn't mind a plugin or extension that does what you suggest. I'm not too familiar with the performance impact of lambda's on the GC, beyond them being singletons as long as you don't pull in state from the side. A way to add this functionality would be to BaseSystem and inject wrapped subscriptions with your own API. The example below doesn't provide component mappers, that would have to be solved separately. I use https://github.com/junkdog/artemis-odb/wiki/Fluid-Entities to avoid those. public class MySystem extends BaseSystem {
@All(Countdown.class)
MySubscription countdowns;
protected abstract void processSystem() {
for(Entity e : countdowns) {
}
}
} public class MySubscriptionAspectResolver implements FieldResolver {
// we need to delegate to the aspect field resolver.
private AspectFieldResolver aspectFieldResolver = new AspectFieldResolver();
@Override
public void initialize(World world) {
aspectFieldResolver.initialize(world);
}
@Override
public Object resolve(Object target, Class<?> fieldType, Field field) {
if (MySubscription.class == fieldType) {
return new MySubscription(
((EntitySubscription) aspectFieldResolver.resolve(target, EntitySubscription.class, field)));
}
return null;
}
} public class MySubscription<A,B> implements Iterable<Entity>{
private final EntitySubscription wrappedSubscription;
public ESubscription(EntitySubscription wrappedSubscription) {
this.wrappedSubscription = wrappedSubscription;
}
@Override
public Iterator<Entity> iterator() {
// custom iterator implementation
}
// lambda API
} Beyond that even for small jam games it's fairly easy to lose the big picture when things start to grow. Combining multiple systems is a solution but it feels like a bit of a workaround to the current architecture. A more flexible way to structure and (re)organize game logic would be nice to have, perhaps combined with a less rigid more lightweight alternative to systems. We could do configurable method callsites on systems with components as parameters (assuming we could solve performance issues with some bytecode weaving or proxies). something like: public class Spawning {
@Process
public void doAThing(Player player, Location location, Movement movement) {..}
@Process
public void doAThing2(LocationHistory lch, Location lc) {..}
@Process
public void doAThing3(Countdown cd) {..}
@Process
// other annotations that control iteration and timing behavior.
public void doAThing4(Player player, Location lc) {..}
} |
Currently i strictly divide my code down into seperate systems.
At this moment i have nearly 40 Systems in my hierarchy, each one doing one task.
Of course not all of them are running each frame, out of 40 Systems, probably 3-4 are running each frame.
This targets mostly stuff like movement, network and ai.
This is a little screenshot from some of my systems. If you take a look at the spawn mechanics ( about 10 systems ) you may notice that this gets really, really messy at some point.
Why did i divide the spawn mechanic into so many systems ? Flexibility, the main reason to use an ECS. That spawning mechanic is not running every frame, but if it does... most of the systems are used to transfer data from one component into the other one. I wanted to have it as dynamic as possible, but thats another topic.
Nevertheless this caused a lot of boilerplate code for those systems. Most of them only contain a few lines of code to copy one object into the next step of the spawn mechanic. Instead of one System for each "loop" i could also write one subscribtion... but this is also a lot of boilerplate code.
It would be great to have a feature that allows us to iterate over different aspects in the same system with less boilerplate code.
Something like :
The text was updated successfully, but these errors were encountered: