Group 組合
對于ECS來說,一個典型的"Hello world"就是所謂的"move system"。move system匕争,是一個獲取所有擁有Position以及Velocity組件的Entity横蜒,并且更新他們的Position 信息,讓他們有效的超目標(biāo)Velocity移動的System互亮。當(dāng)我們意識到這個Entity上的其他Component并不重要時,自然就會明白這個道理余素。這個實體可以是人豹休,狗,汽車桨吊,直升機或房子威根。但如果它有一個Position組件和一個Velocity組件,它必須移動视乐。
那我們怎么獲取這些實體呢洛搀?
如Context 章節(jié)中所述,Context管理著所有實體佑淀,因此我們可以向Context請求并遍歷所有Entity留美,從而收集具有Position以及Velocity 的那些Entites。這將是一個非常幼稚(naive)的實現(xiàn)伸刃。針對這種情況下谎砾,我們在Entitas中應(yīng)對措施就是Group。
context.GetGroup(GameMatcher.AllOf(GameMatcher.Position, GameMatcher.Velocity));
在上面的代碼片中捧颅,我們要求一個Context為我們提供一個包含著所有擁有Position以及Velocity的Entities的Group景图。Group中包含的實體都是最新的,這意味著如果您從實體中刪除某個Position碉哑,Entity就會從Group中被移除挚币。如果您將Position和Velocity組件添加到Entity亮蒋,它將直接進(jìn)入該Group。
你可以任意使用Group妆毕,因為他們在內(nèi)部是被重用的慎玖。Context會儲存一個內(nèi)部List保存所有你請求過的Group,所以如果你使用相同的Matcher訪問Group笛粘,你就會獲取到一個已經(jīng)存在的引用凄吏。既然說到Matchers。闰蛔。。
Matcher 匹配器
Matcher是我們?nèi)绾蚊枋鑫覀兏信d趣的Entity的一種方式图柏。你可以說它就是我們的小型查詢語言(query language)序六。 GameMatcher
意味著我們有一個Game
Context(請參閱Context章節(jié)中的多個Context類型部分),我們可以訪問與此Context相關(guān)的所有Component類型蚤吹。如果我們寫context.GetGroup(GameMatcher.Position);
我們會得到一組包含Position
組件的Entites例诀。為了定義更復(fù)雜的Group,我們可以使用AllOf
裁着,AnyOf
和NoneOf
方法繁涂。 “AllOf”表示所有列出的Component都必須出現(xiàn)在Entity中才能使此Entity成為Group的一部分;“AnyOf”表示必須存在列出的組件中的一個二驰;而在NoneOf
的情況下扔罪,我們則不希望任何列出的組件存在。 NoneOf
不是一個獨立的描述桶雀,這意味著你將無法編寫context.GetGroup(GameMatcher.NoneOf(GameMatcher.Position));
因為它會創(chuàng)建一個非常大的集合矿酵,所以是被禁止單獨使用的。 NoneOf
只能與AllOf
或AnyOf
結(jié)合使用矗积。
context.GetGroup(GameMatcher.AllOf(GameMatcher.Position, GameMatcher.Velocity).NoneOf(GameMatcher.NotMovable));
這樣子我們就能得到一個擁有Position
,Velocity
但是又沒有NotMovable
組件的Group Of Entities了全肮。
AllOf
和 AnyOf
也能被組合成: context.GetGroup(Matcher.AllOf(Matcher.A, Matcher.B).AnyOf(Matcher.C, Matcher.D).NoneOf(Matcher.E))
matcher也能是從AnyOf
開始的: context.GetGroup(Matcher.AnyOf(Matcher.C, Matcher.D).NoneOf(Matcher.E))
Group observation 組合的觀察
就像我說過的,Group永遠(yuǎn)都是最新的棘捣,所以他會提供一個非常方便的方法讓我們觀察它辜腺,并且當(dāng)Entity加入、移除時接收到通知乍恐。更重要的是评疗,但我們replace(置換)一個entity上的component時,舊的component會被移除然后加上新的component禁熏。這就意味著我們的entity會暫時離開然后馬上重新加入group壤巷。這就給我們的響應(yīng)式編程提供一個良好的基礎(chǔ)。
在Entitas-CSharp中瞧毙,我們不會真的刪除或者添加一個Component胧华。生成出來的代碼會先向用戶請求新的值寄症,觸發(fā)移除component的事件,設(shè)置一個新的值給這個component矩动,然后觸發(fā)一次增加component的事件有巧。用這個方法,我們就避免了內(nèi)存的分配以及模擬了一個在使用不可修改
(immutable)component的感覺悲没。
Group里面有這幾種事件可以監(jiān)聽:
- OnEntityAdded
- OnEntityRemoved
- OnEntityUpdated
其他的原料像Collector篮迎,Index以及Reactive system都是使用這些事件。所以如果你只是日常使用的話示姿,你完全可以直接用他們甜橱。但是如果你想制作一些自定義的東西,你可能需要了解其中的實現(xiàn)細(xì)節(jié)栈戳。