-
Because systems can be shared across multiple stores and therefore have a list of queries, one for each store, what's the intended way to set up a second query within a system? For example: public sealed class SomeSystem : QuerySystem<SomeComponent> {
private ArchetypeQuery m_someQuery;
protected override void OnUpdate() {
// How would I use m_someQuery in here?
Query.ForEachEntity((ref SomeComponent someComponent, Entity e) => {
// m_someQuery.ForEachEntity...
}
}
} There are many examples where this kind of thing is useful, but an easy example could be iterating over all network objects and then doing a nested iteration loop over all clients to send them information about the objects. It seems I would need to manage a list or hashmap of my custom query to account for multiple stores and account for when the system is removed / added to stores, but that sounds like a lot of work for something so simple—assuming I didn't want to recreate the query every frame (sounds wasteful). |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
I agree, I think it's must have feature. Let me show an example of API from some different ECS, how it's possible to implement and in what situation it may be useful: public class TriggerWhenOwnerHealthBelowSystem : SystemBase
{
// several queries (groups) in system
private Group _triggerQuery;
private Group _charactersQuery;
protected override void Initialize()
{
// initialization of queries
_triggerQuery = CreateQuery()
.RequireTag<TriggerWhenOwnerHealthBelow>()
.Require<TargetCharacterLink>()
.EnsureNotEmpty(); // execute method wan't be called if query is empty (performance trick remove overhead for virtual calls if no data to process)
_charactersQuery = CreateQuery()
.Require<Character>()
.Require<HealthFraction>()
.EnsureNotEmpty();
}
protected override void Execute()
{
var entities = _triggerQuery.Entities; // get query entities
var whenBelow = _triggerQuery.GetComponents<TriggerWhenOwnerHealthBelow>(); // get query Component data
var triggerTargets = _triggerQuery.GetComponents<TargetCharacterLink>().Reinterpret<Entity>();
var players = _charactersQuery.Entities;
var healthFractions = _charactersQuery.GetComponentsExtended(Arena, HealthFraction.Max);
var filter = NativeMemoryPool.Take<bool>(entities.Length);
for (int i = 0, length = _triggerQuery.Length; i != length; ++i)
{
var playerIndex = players.BinarySearchIndexUnsigned(triggerTargets[i]); // find entity index in array of player entities
// calculate condition for each trigger and store result into array
filter[i] = healthFractions[playerIndex].Value < whenBelow[i].Value;
}
//batch mark all triggers with tag TriggerWhenOwnerHealthBelow as active
World.AddTags<ActionTriggerIsActiveTag>(entities, filter);
}
} |
Beta Was this translation helpful? Give feedback.
Late answer caused by focus of final release v3.0.0 - sorry.
But anyway.
I added an example to the documentation which enables execution of nested queries.
See: https://friflo.gitbook.io/friflo.engine.ecs/documentation/systems#custom-system
So for the given code snippet it would kook like: