最近随着守望先锋制做组在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也处于不断学习理解的状态,但愿能够共同进步