最近隨着守望先鋒製做組在gdc上發佈的一個關於ecs的talk,ecs這個架構算是獲得了必定的曝光度。php
在這以前,github上就一直有一個C#的ecs框架名爲Entitas,截止如今已經有1300+的star了,同時提供了和unity整合的方法(對,你能夠不用unity,直接把它當C#的庫來作其餘的東西)
地址: https://github.com/sschmid/Entitas-CSharp
同時還有一個gitter:https://gitter.im/sschmid/Entitas-CSharp 不少entitas的開發者會在上面進行相關的問答,推薦時不時看兩眼。html
還有云風大大對守望先鋒的talk的解析,http://blog.codingnow.com/2017/06/overwatch_ecs.html 推薦在用Entitas一段時間,熟悉ECS以後再看,寫的很是棒。git
要是對ecs有必定理解的人(一系列很不錯的文章在 http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/ ,主要是講ecs相對oop的優勢的,將OOP在MMORPG開發中的弊端批判了一番),能夠知道ecs的優勢之一在於緩存命中率極高。由於設計良好時,同一類component在內存中是連續排列的。可是出於種種緣由,C#難以寫出一個足夠flexible的框架來實現這一優勢。而Entitas使用了生成代碼的方法,將這一優勢保留了下來,同時也會生成很是友好的API以供調用。程序員
目前Entitas的版本在0.42.3,算是尚未徹底成型,可是知足我這種小打小鬧寫代碼是徹底能夠的。github
提到Entitas,就不得不說一下Unity中GameObject-Component的設計。有人認爲Unity中這種架構也是ECS架構,但事實上緩存
總的來講,Unity中的架構,更多的是OOP中的「組合優於繼承」這一思想的實踐,而不是真正的ECS。架構
回到Entitas上來。Entitas初學者廣泛存在的一個問題是Entitas如何和Untiy交互,由於它們的Entity和GameObject並不存在任何實質上的聯繫。(你把Entitas的代碼拿到Unity外面,徹底能夠運行,若是你沒有用Unity的API的話)框架
這裏先推薦一篇他們本身的talk:https://www.youtube.com/watch?v=lNTaC-JWmdI ,若是能看懂的話那這個問題基本上就解決了。函數
這裏再簡單的說一下個人思路。通常來講,我傾向於理解Unity做爲一個「展現」的工具。全部遊戲的邏輯都在Entitas中運行。工具
若是我要一個Entitas中的Entity在Unity中顯示的話,我會添加一個ViewComponent,包含一個GameObject字段,表示它在Untiy中對應的GameObject。
而後添加一個ViewPositionUpdateSystem,它對有ViewComponent和PositionComponent的Entity感興趣,會在PositionComponent改變時,將ViewComponent中的View也改變位置,此時Unity中你看到的GameObject的位置也就跟着改變了。
這裏題外話一點,在通常的ECS介紹文章中,會從相似「物理系統只關心有PhysicsComponent的Entity,渲染系統只關心有RenderComponent的Entity「相似的話開始。在這裏,咱們也作了相似的事情。只不過咱們的「渲染系統」的渲染工做要簡單得多,只須要把Unity裏的GameObject的位置挪一挪就好了。
再說說物理系統。若是你心大的話,徹底能夠去找一個第三方庫跟Entitas直接接軌,可是用Unity的物理系統也是能夠的。關鍵點和上面同樣,將Unity視做一個工具。
首先,既然你用Unity的物理系統,那你想要的Entity確定得有個ViewCompoennt,而後他的GameObject上有你配置好的碰撞體等。接着你能夠在它的GameObject上添加腳本,在OnTriggerEnter等物理相關的函數中通知Entitas發生了物理碰撞。你能夠寫一個CollisionComponent,其中保存碰撞的信息,在OnTriggerEnter中填寫它添加到Entity上去;也能夠不添加到Entity上,而是直接放在Contexts中等着感興趣的人去處理它(你能夠添加到一個全局Component的List裏,也能夠直接新建一個Entity放那兒,都行)。
這其中比較細節的地方是在OnTriggerEnter中填寫碰撞信息。有人可能發現了,咱們在Entitas的Entity中在ViewComponent裏保存GameObject的索引,可是咱們在OnTriggerEnter中,咱們並不能反過來得到Entity的索引。其實道理是同樣的,咱們能夠寫一個MonoBehaviour,其中有一個Entity字段;在你將一個GameObject用ViewCompoent添加到Entity上時,同時給這個GameObject也添加這個Monobehaviour,寫上Entity的索引就好了。
由於這個需求實在太常見了,Entitas裏內置了一個方法,將Entity和GameObject連接起來。在命名空間Entitas.Unity中提供了GameObject的擴展方法Link,調用該方法的效果跟上一段所說相同,會添加一個叫EntityLink的MonoBehaviour,而後就能夠經過這個MonoBehaviour獲取到它連接的Entity了。
另外若是有任何問題的話歡迎回復或者私信討論,本人對ECS也處於不斷學習理解的狀態,但願能夠共同進步