最近随着守望先锋制作组在gdc上发布的一个关于ecs的talk,ecs这个架构算是得到了一定的曝光度。

在这之前,github上就一直有一个C#的ecs框架名为Entitas,截止现在已经有1300+的star了,同时提供了和unity整合的方法(对,你可以不用unity,直接把它当C#的库来做其他的东西)
地址: https://github.com/sschmid/Entitas-CSharp
同时还有一个gitter:https://gitter.im/sschmid/Entitas-CSharp 很多entitas的开发者会在上面进行相关的问答,推荐时不时看两眼。

还有云风大大对守望先锋的talk的解析,http://blog.codingnow.com/2017/06/overwatch_ecs.html 推荐在用Entitas一段时间,熟悉ECS之后再看,写的非常棒。

要是对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,算是还没有完全成型,但是满足我这种小打小闹写代码是完全可以的。

提到Entitas,就不得不说一下Unity中GameObject-Component的设计。有人认为Unity中这种架构也是ECS架构,但事实上

  1. Unity中的Component都是一个完整的类,缓存不友好。
  2. Unity中的Component包含逻辑。当然你也可以要求出程序员不能在Component里写Update等函数。
  3. Unity中你没办法去获取所有“有ComponentA和ComponentB的所有GameObject”,而在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也处于不断学习理解的状态,希望可以共同进步

Unity下的ECS框架 Entitas简介的更多相关文章

  1. Unity下的开发框架--适应web和微端游戏异步资源请求的框架

    一.   内容简介: 1.   框架对Web与微端游戏特性的支持: Web和微端游戏最重要的特性是,资源是持续从服务器上即时下载下来的.而保证体验流畅的关键就是保证资源下载分散到持续的体验过程中,并保 ...

  2. 理解ECS的概念和Unity中的ECS设计

    组合优于继承 ecs的概念很早就有了,最初的主要目的应该还是为了改善设计. e-c-s三者都有其意义,e-c是组合优于继承,主要用以改善oo的继承耦合过重以及多继承菱形问题. oop常见设计里,每个g ...

  3. 从零开始写一个武侠冒险游戏-0-开发框架Codea简介

    从零开始写一个武侠冒险游戏-0-开发框架Codea简介 作者:FreeBlues 修订记录 2016.06.21 初稿完成. 2016.08.03 增加对 XCode 项目文件的说明. 概述 本游戏全 ...

  4. android hook 框架 libinject2 简介、编译、运行

    Android so注入-libinject2 简介.编译.运行 Android so注入-libinject2  如何实现so注入 Android so注入-Libinject 如何实现so注入 A ...

  5. 出售一套Unity + Lua热更新框架代码

    出售一套Unity + Lua的客户端框架代码,功能有资源管理.网络通信.配置文件解析.热更新.文件读写.Lua加密揭秘.UI框架.打包工具.编辑器工具等,已经在多个实际项目(已上线)中使用.代码优雅 ...

  6. 无废话Android之android下junit测试框架配置、保存文件到手机内存、android下文件访问的权限、保存文件到SD卡、获取SD卡大小、使用SharedPreferences进行数据存储、使用Pull解析器操作XML文件、android下操作sqlite数据库和事务(2)

    1.android下junit测试框架配置 单元测试需要在手机中进行安装测试 (1).在清单文件中manifest节点下配置如下节点 <instrumentation android:name= ...

  7. Debian下安装Firefox与flash简介

    Debian下安装Firefox与flash简介 由于Debian在Firefox的版权上出现了问题,导致官方发布的Debian系统不能使用默认的Firefox浏览器,最后官方重编的Firefox改名 ...

  8. Net Core下多种ORM框架特性及性能对比

    在.NET Framework下有许多ORM框架,最著名的无外乎是Entity Framework,它拥有悠久的历史以及便捷的语法,在占有率上一路领先.但随着Dapper的出现,它的地位受到了威胁,本 ...

  9. windows环境下安装yaf框架

    windows环境下安装yaf框架 在windows下安装yaf框架 准备工作: php环境(过程略,wamp,xampp,phpstudy都行,php版本大于5.3) git工具(需要从github ...

随机推荐

  1. OSI参考模型和TCP/IP参考模型

  2. 第49天:封装自己的scrollTop

    一.scroll家族 offset 自己的偏移scroll滚动的 scrollTop和scrollLeftscrollTop 被卷去的头部当滑动滚轮浏览网页的时候,网页隐藏在屏幕上方的距离二.页面滚动 ...

  3. 第33天:封装自己的class类

    封装自己的class类,实现浏览器兼容. <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  4. Spring Boot 最简单的HelloWorld

    创建一个Spring Boot,可以直接使用构建工具(Maven或Gradle)创建,也可以使用spring.io网站创建,一般会选择使用spring.io创建 使用IDEA创建一个Spring Bo ...

  5. Android开发中如何解析Json

    解析Json 有了请求,自然会有响应,那我们该如何解析服务端响应返回给我们的Json数据呢? 了解什么是Json JSON(JavaScript object notation)是一种轻量级的数据交换 ...

  6. 【刷题】SPOJ 705 SUBST1 - New Distinct Substrings

    Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...

  7. [洛谷P4721]【模板】分治 FFT_求逆

    题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求: $$f_i=\sum_{j=1}^if_{i-j}g_j\\f_0=1$$ 题解:分治$FFT$博客,发现 ...

  8. POJ3304:Segments——题解

    http://poj.org/problem?id=3304 题目大意:给n条线段,求是否存在一条直线,将所有线段投影到上面,使得所有投影至少交于一点. ——————————————————————— ...

  9. [bzoj] 2049 洞穴勘探 || LCT

    原题 这是一道LCT的板子题. 至于LCT--link cut tree,也叫动态树,用splay实现动态连边的树. 预备知识: 实边:一个非叶节点,向它的儿子中的一个连一条特殊的边,称为实边;该非叶 ...

  10. iOS图片上传后被旋转的问题

    最近用PHP做了一个图片合成程序,前端是通过HTML的file input选取自定图片,POST到php后台调整尺寸后与事先准备好的背景图进行合成. 通过测试发现,上传后的自定图片有的被旋转了,有的是 ...