[Solved] EntityQuery.SetFilter doesn't work?

For some reason, I’m getting:

InvalidOperationException: Trying to get iterator for Components.Units.OwnerControlGroup but the required component type was not declared in the EntityGroup.

As soon as I try to apply a filter to:

EntityQuery query = EntityManager.CreateEntityQuery(typeof(OwnerControlGroup),
                                                    ComponentType.ReadOnly<Unit>(),
                                                    ComponentType.ReadOnly<Translation>());
query.SetFilter(new OwnerControlGroup(id));

I’ve tried ComponentType.ReadOnly, and ReadWrite with the same result.

GetEntityQuery fails the same way.

OwnerControlGroup is defined as this:

using Unity.Entities;
namespace Components.Units {
    public struct OwnerControlGroup : ISharedComponentData {
        public int ControlId;

        public OwnerControlGroup(int controlId) {
            ControlId = controlId;
        }
    }
}

Units do have a shared component attached to them.

What am I missing?

Where are you calling this code from? Usually you use GetFilter in OnCreate, and then SetFilter in OnUpdate. If used otherwise I doubt it would cause issues but maybe?

A complete shot in the dark, but maybe the constructor is throwing things off? Unity creates a default shared component of your type, and maybe the lack of a parameter-less constructor is throwing off this process. I would add one, and if that doesn’t work, try removing the constructor. When doing the latter, if you have a lot of new OwnerControlGroup(ID) lines, you could do a Find/Replace and switch them to new OwnerControlGroup { ControlID = ID}.

Just some ideas with nothing substantial to back them up.

1 Like

I haven’t tried GetFilter I’ll try that. I was just setting filter directly via SetFilter + SharedData (as in manual).

Setting it in both OnCreate and OnUpdate fails for the same reason.

Already tried, same result.

What I think I should do is to debug where data missmatches. Perhaps its a bug.

Show full code, some mistakes on your side, cause SetFilter works fine

public struct CompShared : ISharedComponentData
{
    public int Id;

    public CompShared(int id)
    {
        Id = id;
    }
}

public struct Comp : IComponentData
{
    public int SomeValue;
}

public class FilterSystem : JobComponentSystem
{
    private EntityQuery _query;
    protected override void OnCreateManager()
    {
        _query = GetEntityQuery(typeof(CompShared), ComponentType.ReadOnly<Comp>());

        var shared1 = new CompShared()
        {
            Id = 1
        };
        var shared2 = new CompShared()
        {
            Id = 2
        };
        for (int i = 0; i < 10; i++)
        {
            var e = EntityManager.CreateEntity(typeof(CompShared), typeof(Comp));
            if (i < 7)
                EntityManager.SetSharedComponentData(e, shared1);
            else
                EntityManager.SetSharedComponentData(e, shared2);
        }
    }

    protected override JobHandle OnUpdate(JobHandle deps)
    {
        Debug.Log(_query.CalculateLength());
        _query.SetFilter(new CompShared(2));
        Debug.Log(_query.CalculateLength());
        _query.ResetFilter();
        return deps;
    }
}

1 Like

System:

using Archetypes;
using Components.UI.SelectionBox;
using Components.Units;
using Data;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;

namespace Systems.UI {
    public class SelectionBoxSystem : JobComponentSystem {
        #region [Fields]

        private EntityQuery _boxQuery;
        private EntityQuery _unitQuery;

        private float2 _startScreenPos;
        private float2 _endScreenPos;

        private static Camera _camera;
        private static Transform _cameraTrm;

        private EndSimulationEntityCommandBufferSystem _ecbSystem;

        #endregion

        protected override void OnCreate() {
            _boxQuery = EntityManager.CreateEntityQuery(ArchetypesUI.SelectionBox); // ComponentType[] { SelectionBox }
            RequireSingletonForUpdate<SelectionBox>();

            _unitQuery = GetEntityQuery(ComponentType.ReadOnly<Unit>(),
                                        ComponentType.ReadOnly<Translation>(),
                                        typeof(OwnerControlGroup));
            _unitQuery.SetFilter(new OwnerControlGroup(1)); // Exception here

            _ecbSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
        }

        /// <summary>
        /// Sets a camera to raycast from
        /// </summary>
        public static void SetCamera(Camera camera) {
            _camera = camera;
            _cameraTrm = _camera.transform;
        }

        protected override JobHandle OnUpdate(JobHandle inputDeps) {
            SelectionBox box = _boxQuery.GetSingleton<SelectionBox>();

            _startScreenPos = box.Start;
            _endScreenPos = box.End;

            float2 screenCenter = (_endScreenPos + _startScreenPos) * 0.5f;

            Vector3 vCenter = new Vector3(screenCenter.x, screenCenter.y);
            Vector2 size = math.abs(_startScreenPos - _endScreenPos);

            // Half extents used instead of size
            ScreenBounds selectionBounds = new ScreenBounds(screenCenter, size / 2f);

            return PerformSelectionTest(selectionBounds, inputDeps);
        }

        private JobHandle PerformSelectionTest(ScreenBounds selectionBounds, JobHandle inputDeps) {
            float4x4 vp = _camera.projectionMatrix * _cameraTrm.worldToLocalMatrix;
            float2 screen = new float2(Screen.width, Screen.height);

            EntityCommandBuffer.Concurrent ecb = _ecbSystem.CreateCommandBuffer()
                                                           .ToConcurrent();

            JobHandle job = new SelectionJob {
                                                 Buffer = ecb,
                                                 ViewPort = vp,
                                                 Screen = screen,
                                                 ScreenBounds = selectionBounds
                                             }.Schedule(_unitQuery, inputDeps);

            _ecbSystem.AddJobHandleForProducer(job);

            return job;
        }

        [RequireComponentTag(typeof(Unit))]
        private struct SelectionJob : IJobForEachWithEntity<Translation> {
            [ReadOnly]
            public float4x4 ViewPort;

            [ReadOnly]
            public float2 Screen;

            [ReadOnly]
            public ScreenBounds ScreenBounds;

            public EntityCommandBuffer.Concurrent Buffer;

            public void Execute(Entity entity, int index, [ReadOnly] ref Translation pos) {
                /*Mathy stuff*/
            }
        }
    }
}

Unit:

using Unity.Entities;
namespace Components.Units {
    public struct Unit : IComponentData {
    }
}
using Unity.Entities;
namespace Components.Units {
    public struct OwnerControlGroup : ISharedComponentData {
        public int ControlId;

        public OwnerControlGroup(int controlId) {
            ControlId = controlId;
        }
    }
}

Side advices:

Are you sure error in this system, cause all works fine for me

1 Like

Yes. I guess my potato pc is cursed.

You tested it with IDE attached in debug mode and goes through lines step by step?

1 Like

Yes, I’ve got no idea what’s causing this.

It could be that type is not mapped properly for some reason via TypeManager.

Just to be clear, I’m using Unity 2019.1.11f1 & Entities p33 / 0.0.12

Bloody h. You were right. It was pointing to the different query / system.
How did I managed to miss that?

Okay, lesson learned, read stacktrace more carefully.