圖中可以看到一個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