LibGDX/Ashley has a class IntervalIteratingSystem that allows you to process all entities in a particular family every X milliseconds. But if you have a lot of entities to process, it might be a bad idea to do all that at once. For example, if you want to process 10,000 entities once every 10 seconds, you might not actually want to wait 10 seconds, and then process all the entities -- you'd want to "spread it out" over many frames. Perhaps every 100ms you process 100 entities, cycling through them all.
To rephrase: I'd like to process a large number of entities but spread out across multiple frames, preferably:
- providing a reasonable guarantee that all entities will processed at least once every X seconds,
- enabling you to keep track of how much time has passed since that entity was last processed,
- with a random entity order,
- all entities are processed an equal number of times.
Here are my ideas so far...(some bad, some good)
- Every time an entity is added to the
Engine
, add a Group1, Group2, or GroupN component (either randomly or sequentially), and then in my EntitySystem I cycle through the various families based on their Group#. - Every 10 seconds, add all 10,000 entities to a list, and then every 100ms, drain and process 100 from that list. (Memory-intensive, and might fall behind)
- Every 100ms, iterate over all 10,000 entities, but skip 99% of them randomly (either using a PRNG or by checking their hashcode mod prime).
- Maintain a list (a copy, really) of all relevant entities inside an EntitySystem using
Engine#addEntityListener()
and then process 1% of the list every 100ms by sequentially stepping through it, and wrapping around when reaching the end. (Uses LibGDX's unordered Array so removals are cheap). - Same as 4., but rely on
Engine#getEntitiesFor
and just let Ashley handle ordering and tracking entities instead of keeping a separate list.
At the moment, #1 and #5 seem most promising. #1 seems to meet all my requirements, but is a bit pervasive (creating and adding a bunch of components), #5 is less pervasive, but doesn't meet the requirements quite as well (#2 and #3 mostly).
Thoughts? Is there something better than these?
IsDirty
boolean property to the objects. Run through and "clean" the objects as you've processed them. Once the list is empty, mark them all dirty and cycle again. The benefit I see in this is that your processing entity could take n per cycle, process them and mark them as clean without having to track the order they are in the list. You could also set a priority and a max time value. Higher priority objects are processed first (can be ordered anywhere in the list), and after your max time, all objects are set dirty again in case the timing is off. \$\endgroup\$Gdx-ai
extention you can do this quite easily in a native-gdx way. I'll se if I have time to answer this later otherwise just look up Gdx AI for yourself. \$\endgroup\$