IMatcher
Matcher是EntitasLite提供的一个匹配器,也可以叫筛选器,通过定义一系列Component规则来对Entity进行匹配或筛选。基本结构由IMatcher接口类定义:
这一堆的IMatcher接口乍一看有点乱,仔细一看,还真是有点乱。
没关系,我们继续看实现类Matcher。
Matcher
Matcher是IMatcher接口的实现类,主要内容如下:
上图里没有截到的一点是,Matcher并不是直接实现IMatcher,而是实现的IAllOfMatcher
public partial class Matcher : IAllOfMatcher
Matcher最核心的部分
对于Matcher,我们首先需要了解的有三点:
-
Matcher包含一个int数组 indices,这个数组内的元素是Component的Index,代表着所有与这个Matcher相关的Component,这点在Context的 GetGroup(IMatcher matcher) 方法中已经介绍过了,Context会遍历Matcher的indices数组,分别记录下每个index都被哪些Group所关心。
-
Matcher中还有另外三个int数组:_allOfIndices、_anyOfIndices、_noneOfIndices,分别对应 “必须全部都有的Component”、“有任一即可的Component” 以及 “一个都不能有的Component”。这三个数组分别定义了这个Matcher的三条匹配规则。
indices是这三个数组内元素的去重合并。
/// <summary>
/// 必须要有的Component
/// </summary>
int[] _allOfIndices;
/// <summary>
/// 只要有一个就行的Component
/// </summary>
int[] _anyOfIndices;
/// <summary>
/// 一个都不能有的Component
/// </summary>
int[] _noneOfIndices;
需要注意的一点是,这三个数组初始是没有赋值的,都为null,也就是说,刚创建的Matcher是没有定义任何匹配规则的,需要使用者手动对规则进行指定。
- Matcher中提供了一个Matches(Entity entity)方法,对Entity执行筛选行为,返回该Entity是否满足当前Matcher的匹配规则:
public bool Matches(Entity entity)
{
return (_allOfIndices == null || entity.HasComponents(_allOfIndices))
&& (_anyOfIndices == null || entity.HasAnyComponent(_anyOfIndices))
&& (_noneOfIndices == null || !entity.HasAnyComponent(_noneOfIndices));
}
筛选过程很简单,如果Matcher中的某一条匹配规则被指定了,就调用Entity对应的方法,对身上的Component进行检查,以判断是否满足。
以上就是Matcher最核心的部分。
两个重要的静态方法
Matcher还提供了静态方法,用于创建不同匹配的实例:
public static IAllOfMatcher AllOf(params int[] indices)
public static IAllOfMatcher AllOf(params IMatcher[] matchers)
public static IAnyOfMatcher AnyOf(params int[] indices)
public static IAnyOfMatcher AnyOf(params IMatcher[] matchers)
我们会发现,为什么只给了 AllIOf 和 AnyOf 的方法,却没有给 NoneOf 呢?原因主要是为了迅速缩小目标范围:
- Matcher的作用是从Context中根据Component规则快速筛选出一系列的Entity
- Matcher通过一种层层向下筛选的方式来使用
一堆Entity中找出含有某个Component的Entity,数量明显要比不含某个Component的Entity的数量要少的多。因此,EntitasLite默认筛选过程必须以 AllOf 或者 AnyOf 的方式起手,不允许 NoneOf 起手。哒咩。
其中以int数组为参数的两个方法是最常用的方法,内容如下:
public static IAllOfMatcher AllOf(params int[] indices)
{
var matcher = new Matcher();
//为 AllOf 指定匹配规则
// distinctIndices 方法是列表去重
matcher._allOfIndices = distinctIndices(indices);
return matcher;
}
public static IAnyOfMatcher AnyOf(params int[] indices)
{
var matcher = new Matcher();
//为 AnyOf 指定匹配规则
// distinctIndices 方法是列表去重
matcher._anyOfIndices = distinctIndices(indices);
return matcher;
}
其实就是生成一个对应类型的Matcher,同时为这个Matcher的某一条匹配规则进行指定。通过这两个静态方法,可以获得一个 IAllOfMatcher 的实例或一个 IAnyOfMatcher 的实例。
两个重要的实例方法
- 当我们获得是 IAnyOfMatcher 实例的时候,Matcher中实现了 IAnyOfMatcher 接口的 NoneOf 方法:
public INoneOfMatcher NoneOf(params int[] indices)
{
_noneOfIndices = distinctIndices(indices);
_indices = null;
_isHashCached = false;
return this;
}
这个方法对任意类型的Matcher实例都可见,因此我们可以继续通过该方法对结果指定进一步筛选的规则,就像下面这样:
IMatcher _finalMatcher = Matcher.AnyOf(ComponentIndex<InputComponent>.FindIn<Default>(), ComponentIndex<ViewComponent>.FindIn<Default>()).
NoneOf(ComponentIndex<ThirdPersonComponent>.FindIn<Default>());
- 当我们获得的是一个 IAllOfMatcher 实例的时候,由于 IAllOfMatcher 实现自 IAnyOfMatcher , 我们同样可以像上面那样通过NoneOf指定进一步筛选的规则:
IMatcher _finalMatcher = Matcher.AllOf(ComponentIndex<InputComponent>.FindIn<Default>(), ComponentIndex<ViewComponent>.FindIn<Default>()).
NoneOf(ComponentIndex<ThirdPersonComponent>.FindIn<Default>());
同时,Matcher还显式实现了 IAllOfMatcher 的 AnyOf 方法:
IAnyOfMatcher IAllOfMatcher.AnyOf(params int[] indices)
{
_anyOfIndices = distinctIndices(indices);
_indices = null;
_isHashCached = false;
return this;
}
所以 IAllOfMatcher 的实例除了 NoneOf 之外,还多了一个 通过 AnyOf 进行进一步筛选的功能:
IMatcher _finalMatcher = Matcher.AllOf(ComponentIndex<InputComponent>.FindIn<Default>(), ComponentIndex<ViewComponent>.FindIn<Default>()).
AnyOf(ComponentIndex<ThirdPersonComponent>.FindIn<Default>());
综上,IMatcher那个看起来很乱的继承关系,总结下来其实就是通过接口内方法数量来限制不同类型Matcher实例的功能全面性:
- IAllOfMatcher 功能是最全的,IAnyOfMatcher 其次, INoneOfMatcher则只具有Matcher的核心功能
- 制定最终的finalMatcher时,根据不同类型Matcher的功能全面性来安排顺序
- 只要匹配规则中包含了 AllOf 规则,那就通过 Matcher.AllOf 静态方法起手,然后再看是否有 AnyOf 的规则,最后看是否有 NoneOf 的规则
- 在不包含 AllOf 规则时,就通过 Matcher.AnyOf 静态方法起手,然后看是否有 NoneOf 的规则
IMatcher _finalMatcher = Matcher.AllOf(ComponentIndex<InputComponent>.FindIn<Default>()).
AnyOf(ComponentIndex<ViewComponent>.FindIn<Default>()).
NoneOf(ComponentIndex<ThirdPersonComponent>.FindIn<Default>());
标签:分析,IAllOfMatcher,Matcher,Component,IMatcher,源码,EntitasLite,indices,AnyOf
From: https://blog.csdn.net/zhiai315/article/details/144108130