(转)我所理解的Entitas——Matcher Collector(五)

图中可以看到一个Context具有多个Entity,每个Entity可能会被N个Group所关心。

Group
一个Context中可能会同时存在很多个Entity,但是有些时候我们只需要处理某些Entity,那么我们可以通过Group来快速访问,每个Context内部维护一个Group对象集合,调用GetGroup()方法可以拿到Group,相同得Matcher参数拿到得是相同得Group对象。
Group是实时更新的一个具有相同筛选条件的Entity的组合,它会自动添加具有筛选条件的Entity,并删除失去筛选条件的Entity,以提高下一次的访问速度。

public IGroup<TEntity> GetGroup(IMatcher<TEntity> matcher)
    {
        if (!_groups.TryGetValue(matcher, out IGroup<TEntity> group))
        {
            group = new Group<TEntity>(matcher);
            TEntity[] entities = GetEntities();
            for (int i = 0; i < entities.Length; i++)
            {
                group.HandleEntitySilently(entities[i]);
            }
            _groups.Add(matcher, group);
            for (int j = 0; j < matcher.indices.Length; j++)
            {
                int num = matcher.indices[j];
                if (_groupsForIndex[num] == null)
                {
                    _groupsForIndex[num] = new List<IGroup<TEntity>>();
                }
                _groupsForIndex[num].Add(group);
            }
            if (this.OnGroupCreated != null)
            {
                this.OnGroupCreated(this, group);
            }
        }
        return group;
    }

可以通过GetEntities()拿到Group中得所有Entity。通过ContainsEntity()接口判断Group中是否包含某个Entity。

Gorup提供了OnEntityAdded,OnEntityRemoved,OnEntityUpdated事件委托监听Group内部得Entity变化。

gameContext.GetGroup(GameMatcher.Position).OnEntityAdded += (group, entity, index, component) => {
        // Do something
    };

Matcher

Matcher是Group的筛选条件,筛选条件就是Context中所拥有的Component。
例:
我们有MoveComponent和AttackComponent两个组件存在Game Context中。则我们可以有一下几种查询方式:

//查找所有有MoveComponent的Entity
    var moveEntitys = contexts.game.GetGroup(GameMatcher.Move);

    //查找所有有AttackComponent的Entity
    var attackEntitys = contexts.game.GetGroup(GameMatcher.Attack);

    //查找所有有MoveComponent和AttackComponent的Entity
    int[] allMatcher = { GameComponentsLookup.Move,GameComponentsLookup.Attack };
    var AllEntitys = contexts.game.GetGroup(GameMatcher.AllOf(allMatcher));

    //查找所有有MoveComponent或AttackComponent的Entity
    int[] anyMatcher = { GameComponentsLookup.Move, GameComponentsLookup.Attack };
    var AnyEntitys = contexts.game.GetGroup(GameMatcher.AnyOf(anyMatcher));

Collector
通过Group和Matcher已经可以拿到所有符合条件的Entity,例如所有具有MoveComponent的Entity。也说过了Group会实时更新,但是如果我们需要知道Group中当前哪些Entity是新加进来的。则可以通过Collector来找到。
例:

//查找所有有MoveComponent的Entity
    var moveEntitys = contexts.game.GetGroup(GameMatcher.Move);
    //找到哪些Entity是刚刚获得了MoveComponent然后被添加到Gorup中的
    var collect = moveEntitys.CreateCollector<GameEntity>(GroupEvent.Added);

GroupEvent

+ Added         添加到Gorup中的
+ Removed       从Group中移除的
+ AddedOrRemoved    所有变化的(包含添加的和移除的)

 

总结:
前面说过了空军指挥部(System_3)可以指挥拥有开飞机(Component_3)技能的士兵(Entity)飞往指定的地方完成任务A,那么就需要通过Group拿到所有能开飞机(Component_3)的士兵(Entity)。
但是可能所有能开飞机(Component_3)的士兵(Entity)都在执行任务B,这时候可以加班训练新的士兵(Entity)让其拥有开飞机(Component_3)的技能,然后通过Collector找到这些刚刚学会开飞机(Component_3)技能又不在出任务的士兵(Entity)去完成任务A。

原文地址:https://blog.csdn.net/u010020342/article/details/109898655?spm=1001.2014.3001.5502

 

posted @ 2023-07-15 19:34  星月相随  阅读(29)  评论(0编辑  收藏  举报