Pass on data

Passing on data, a way to use data from outside in your queries

In many cases, it is simply not enough to work with data on the entities alone. Sometimes you also need data from outside... but how do you even do that?

Closure

The easiest way is to transfer the value directly to the query. This is called Closure. It is simple, but not particularly efficient. For most purposes, however, it will suffice.


World.Query(in queryDesc, (ref Position pos, ref Velocity vel) => {
    
});

Alternatively, you can cache the static value, which avoids the allocation. This is not possible everywhere, but where it works, it works wonderfully.

var intruderPosition = DetectIntruder();
World.Query(in queryDesc,  (ref Position pos, ref Velocity vel) => {
    MoveTowards(ref pos, ref vel, intruderPosition);
});

And already all our entities are moving in the direction of the intruder, brilliant... right?

Inline query

Another way is to pass on the values using a Struct. For this we can use the InlineQuery and the IForEach interface.

private struct VelocityUpdate: IForEach<Position, Velocity>
{
    public Position IntruderPosition;
    
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Update(ref Position pos, ref Velocity vel)
    {
        MoveTowards(ref pos, ref vel, IntruderPosition);
    }
}

var velUpdate = new VelocityUpdate{ IntruderPosition = DetectIntruder(); };
World.InlineQuery<VelocityUpdate, Position, Velocity>(in queryDesc, ref velUpdate);

Now our entities are also moving in the direction of the intruder... but more efficiently. Especially good if we have a lot of entities. It's also quite nice, isn't it? But there is another variant.

Custom loop

That's not enough for you? Well, then we have one last ace up our sleeve. You can also write queries yourself!

You can now iterate archetypes and chunks yourself, which removes any abstraction. This in turn allows you to pass values and logic however you want.

var intruderPosition = DetectIntruder();
var queryDesc = new QueryDescription().WithAll<Position, Velocity>();


foreach (ref var chunk in query)
{
    
    var velocities = chunk.GetSpan<Velocity>();
    
    
    {
        ref var pos = ref positions[entityIndex];
        ref var vel = ref velocities[entityIndex];
        
        MoveTowards(ref pos, ref vel, intruderPosition);
    }
}

And now you can move even more entities efficiently, perhaps even hundreds of thousands? Or even millions? Who knows, time to let them march!

Last updated

Was this helpful?