#Is this how I'm supposed to write to components from a query in a parallel job?

1 messages · Page 1 of 1 (latest)

boreal mesa
#

I'm trying to write to a component data array that's come from a query in a IJobParallelFor, but it's not doing anything. I'm a little dizzy and lost searching through the docs at this stage, so would appreciate any pointers into what I'm doing wrong!

Here's a minimal example of where I've ended up. Logs on next message because I'm out of letters here.

    public partial class TestSystem : SystemBase
    {
        struct DoMovementJibJob : IJobParallelFor
        {
            public NativeArray<MovementData> MovementDatas;

            public void Execute(int index)
            {
                UnityEngine.Debug.Log($"1 {MovementDatas[index].SkipNextTick}");
                var movementData = MovementDatas[index];

                if (movementData.SkipNextTick)
                {
                    UnityEngine.Debug.Log($"1a");
                    movementData.SkipNextTick= false;
                    MovementDatas[index] = movementData;
                    UnityEngine.Debug.Log($"1b {MovementDatas[index].SkipNextTick}");
                    return;
                }

                UnityEngine.Debug.Log($"2");
            }
        }

        EntityQuery _query;

        protected override void OnCreate()
        {
            base.OnCreate();
            _query = EntityManager.CreateEntityQuery(ComponentType.ReadWrite<MovementData>());
        }

        protected override void OnUpdate()
        {
            UnityEngine.Debug.Log($"TICK {MRefs.Ctx.Tick}"); // Tick is the tick number, e.g. 1 then 2 then 3

            var rwMovementDatas = _query.ToComponentDataArray<MovementData>(Allocator.TempJob);

            new DoMovementJibJob
            {
                MovementDatas = rwMovementDatas,
            }.Schedule(arrayLength: rwMovementDatas.Length, innerloopBatchCount: 5).Complete();

            UnityEngine.Debug.Log($"TICK COMPLETE");
        }
    }
#

Here are the logs for above, with some added comments to help describe the issue:

TICK 1
1 True         # before, is true
1a
1b False       # after (still in the job though), is false
TICK COMPLETE
TICK 2
1 True         # why's this true again? it should be false
1a
1b False
TICK COMPLETE
TICK 3
1 True
1a
1b False
TICK COMPLETE
slate coyote
#

what is your reasoning for using IJobParallelFor over a proper entity job that just supports this natively

#

you're only writing to a copy of the data

#

not the actual entity

#

ToComponentDataArray just makes a copy

boreal mesa
#

But also I dunno what a "proper entity job" is 😅

I've just started converting all my Entities.ForEach and Job.WithCodes to these jobs so am not sure of all the options

slate coyote
#

that is a terrible example

boreal mesa
#

😅

slate coyote
#

as your replacement to Entities.ForEach

boreal mesa
#

Oo so IJobEntity seems like it works similarly to Entities.ForEach with the magic parameters?

#

Wonderful

slate coyote
#

yes it's EFE but just better

boreal mesa
#

Ok will try! Thanks tertle ❤️

#

Interestingly I cannot .Complete() it

slate coyote
#

you should be able to

boreal mesa
#

Ah I need to give it a job handle if I want it to return one

slate coyote
#

yes

#

alternatively just do the auto generation dependency handles

#

and just call

#

state.Dependency.Complete()

#

on the next line

boreal mesa
#
TICK 1
1a
TICK COMPLETE
TICK 2
2
TICK COMPLETE
TICK 3
2
TICK COMPLETE

omg thank you

boreal mesa
#

Hmm, new problem. I have a ComponentLookup<MovementData> already defined and being passed around to many jobs (arbitrary writing situation while trying to avoid sync points), and this IJobEntity query is internally creating a new one to support that magic parameter, which causes aliasing issues.

Is there a way I can supply a query to this IJobEntity and then instead of having a ref MovementData parameter, I can make the job write to the same component lookup that already exists? Noting the parallel safety concerns - I can enforce having no other job reading/writing to the lookup at the same time.

#

My guess is that I can build a query that has a WithAll filter that requires the MovementData to exist, but doesn't actually create a ComponentLookup for it if I don't add that as a magic parameter 🤔