(轉)我所理解的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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章