在Unity ECS 1.0中,对ISystems和SystemBase的实体查询

huangapple go评论100阅读模式
英文:

Entity Query for ISystems and SystemBase in Unity ECS 1.0

问题

我在Unity ECS 1.0中有一个基于瓦片的建筑游戏,在其中我向多个系统添加了特定的IComponentData。从一个MonoBehavior(因为PlayerInputInputActions没有被转换为ECS),我尝试查询所有具有该IComponentData的系统。但我发现常规的EntityQueries不匹配系统的Entity表示,所以我不得不使用EntityManager.UniversalQueryWithSystems,它返回所有系统的Entity表示。然后我使用for循环检查所有系统是否具有该特定组件。
有人知道是否有更高效的方法来检查这些组件是否存在于系统中吗?
我已经尝试过返回EntityManager.UniversalQueryWithSystems.ToComponentDataArray<MyComponent>(),但然后它会抱怨说,该查询没有使用此组件进行初始化(当然,我不能更改它,因为这不是我的自定义查询)。

英文:

I have a tile based building game in Unity ECS 1.0, where I add particular IComponentData to several systems. From a PlayerInput which is a MonoBehavior (because PlayerInput and InputActions are not translated to ECS), I tried to query all systems having that IComponentData. But I found that regular EntityQueries do not match for Entity representation of systems, so I had to use EntityManager.UniversalQueryWithSystems, which returns the Entity representation of all systems. There I do a for loop and check all systems for that particular component.
Does anybody know if there is a more performant way to check for these components on systems?
I already tried to return EntityManager.UniversalQueryWithSystems.ToComponentDataArray<MyComponent>(), but then it's complaining, that the query have not been initialized using this component (which of course I may not change, as it's not my own query).

答案1

得分: 1

我刚刚找到了。你可以将选项传递给EntityQueryBuilder或调用SystemAPI.Query<>(..)方法并使用.WithOptions(..),然后只需传递EntityQueryOptions.IncludeSystems

因此,完整的调用可能如下所示:

public static NativeArray<Entity> GetSystemsManaged<T>() where T : struct, IComponentData
{
    if (World.DefaultGameObjectInjectionWorld == null
        || !World.DefaultGameObjectInjectionWorld.IsCreated
        || World.DefaultGameObjectInjectionWorld.EntityManager == null)
    {
        return new NativeArray<Entity>(0, Allocator.Temp);
    }
    EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
    EntityQueryBuilder queryBuilder = new EntityQueryBuilder(Allocator.Temp)
        .WithAll<T>()
        .WithOptions(EntityQueryOptions.IncludeSystems);
    EntityQuery entityQuery = entityManager.CreateEntityQuery(queryBuilder);
    NativeArray<Entity> result = entityQuery.ToEntityArray(Allocator.Temp);
    queryBuilder.Dispose();
    entityQuery.Dispose();
    return result;
}

希望这对你有所帮助!

英文:

I just found it. You can pass options to an EntityQueryBuilder or a call to SystemAPI.Query<>(..) with the method .WithOptions(..) then just pass EntityQueryOptions.IncludeSystems.

So a complete call could look like this:

public static NativeArray<Entity> GetSystemsManaged<T>() where T : struct, IComponentData
{
    if (World.DefaultGameObjectInjectionWorld == null
        || !World.DefaultGameObjectInjectionWorld.IsCreated
        || World.DefaultGameObjectInjectionWorld.EntityManager == null)
    {
        return new NativeArray<Entity>(0, Allocator.Temp);
    }
    EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
    EntityQueryBuilder queryBuilder = new EntityQueryBuilder(Allocator.Temp)
        .WithAll<T>()
        .WithOptions(EntityQueryOptions.IncludeSystems);
    EntityQuery entityQuery = entityManager.CreateEntityQuery(queryBuilder);
    NativeArray<Entity> result = entityQuery.ToEntityArray(Allocator.Temp);
    queryBuilder.Dispose();
    entityQuery.Dispose();
    return result;
}

huangapple
  • 本文由 发表于 2023年6月19日 21:38:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76507193.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定