UnityECS学习日记十六:UnityECS使用EntityQuery(实体筛选器)

ECS中所有实体以ID的方式进行存储,正常游戏物体要分很多种类型,还要对不同类型分别进行操作,这就需要筛选器来获取你想要的操作的实体对象进行修改数据。

 

案例十四:EntityQuery(实体筛选器)(Scne15)


用到的ComponetData:

using Unity.Entities;

public struct ComponentA : IComponentData
{
    public int type;
}
public struct ComponentB : IComponentData
{

}
public struct ComponentC : IComponentData
{

}

public struct ComponentD : IComponentData
{

}

public struct ShareComponentA : ISharedComponentData
{
    public int type;
}

下面介绍各种各种筛选方法

第一种:我们先前经常用到的,从场景里获取包含对应组件的实体 : GetEntityQuery() 是抽象类:ComponentSystemBase中的方法

using Unity.Entities;
using Unity.Jobs;

public class Query_GetEntityQuerySystem : JobComponentSystem
{
    private EntityQuery entityQuery;
    protected override void OnCreate()
    {
        // 通过得到只包含ComponentA和ComponentB组件实体的筛选器
        entityQuery = this.GetEntityQuery(typeof(ComponentA), typeof(ComponentB));

    }

    // IJobForEach也可以充当筛选器的作用,但是不如如上灵活方便
    struct EntityQueryJob : IJobForEach<ComponentA>
    {
        public void Execute(ref ComponentA a)
        {

        }
    }

    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        EntityQueryJob entityQueryJob = new EntityQueryJob()
        {

        };
        //讲这个值传入Job使用
        JobHandle jobHandle = entityQueryJob.Schedule(entityQuery, inputDeps);
        jobHandle.Complete();
        return jobHandle;
    }
}

第二种:通过创建EntityQueryDesc对象,它位于Unity.Entites命名空间,该对象内部提供了 Any、None、All三种类型数组。

using Unity.Entities;
using Unity.Jobs;

//对于筛选更为复杂得到实体,或 且 不包含 可以使用EntityQueryDes 筛选器
public class Query_EntityQueryDesSystem : JobComponentSystem
{
    private EntityQuery entityQuery;


    protected override void OnCreate()
    {
        //-- 第一种
        var query = new EntityQueryDesc()
        {
            All = new ComponentType[] { typeof(ComponentA), typeof(ComponentB), typeof(ComponentC) }
        };
        //代表要筛选同时包含这个数组里所有类型的组件的实体。
        this.entityQuery = GetEntityQuery(query);

        //-- 第二种
        var twoQuery = new EntityQueryDesc()
        {
            All = new ComponentType[] { typeof(ComponentA) },
            Any = new ComponentType[] { typeof(ComponentB), typeof(ComponentC) },
            None = new ComponentType[] { typeof(ComponentD) }
        };
        // 筛选必须包含A组件 ,包含 ComponentB或者C组件,不包含D组件的实体!

    }

    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        return inputDeps;
    }
}

第三种:SetFilter (我从其他文章介绍看到的是SetSharedComponentFilter但是这个版本没有该方法我觉得是改成这个名字了) 筛选共享组件,这里操作的数据组件必须得是共享的数据,也就是Data:IShareComponent这种类型的。通过指定条件来实现筛选操作。它属于 EntityQuery中的一个方法。

using Unity.Entities;
using Unity.Jobs;

public class Query_SetSharedComponentFilter : JobComponentSystem
{
    EntityQuery entityQuery;
    protected override void OnCreate()
    {
        entityQuery = GetEntityQuery(typeof(ShareComponentA));
        entityQuery.SetFilter<ShareComponentA>(new ShareComponentA { type = 1 });
        // 注意: 这里的实体上数据结构 是继承自 ISahredComponentData  
    }

    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        return inputDeps;
    }


}

如上,指定筛选的组件type必须为1,再将其传入Job中使用。


第四种:SetFilterChanged(从其他文章看到的是SetSharedComponentFilter),通过判定该实体的指定的组件发生了改变来进行筛选。

using Unity.Entities;
using Unity.Jobs;

public class Query_SetChangedVersionFilter : JobComponentSystem
{
    EntityQuery entityQuery;
    protected override void OnCreate()
    {
        entityQuery = GetEntityQuery(typeof(ComponentA), typeof(ComponentB));
        entityQuery.SetFilterChanged(typeof(ComponentA));
        // 筛选 指定该实体的哪个组件发生了改变
    }

    struct ChangeJob : IJobForEach<ComponentA>
    {
        public void Execute(ref ComponentA comA)
        {
            // 注意我在Job中并没有修改,但是这里也判定了 ComponentA被修改了
        }
    }

    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        return inputDeps;
    }

}

SetFilterChanged 会对指定组件被修改了的进行筛选,注意:这里的被修改,实则是被传入标记了,比如上面Job中 ref 标记读写操作。这也算被修改了。而且这个修改也影响了整个Chunk(块),我的理解是如果对该Chunk使用该筛选方式时,一个实体被标记了整个Chunk也是被标记的。因此平时开发时要对不需要操作的组件进行只读(Readonly)标记。


 

远程项目仓库(github):https://github.com/h1031464180/UnityECS 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值