英文:
Entity Query for ISystems and SystemBase in Unity ECS 1.0
问题
我在Unity ECS 1.0中有一个基于瓦片的建筑游戏,在其中我向多个系统添加了特定的IComponentData
。从一个MonoBehavior
(因为PlayerInput
和InputActions
没有被转换为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;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论