Unity的ECS框架实践

    ECS的概念之前已经听了很久了,Unity也推出了自家的Unity框架Entities,虽然现在还处于preview阶段,不过趁着Unity2018.3推出,抽空学习了一下,写一篇心得分享一下我所理解的ECS模式。
    ECS全称是实体,组件,系统。我个人理解的Unity原先的组件式的开发是基于EC的,其中的GameObject相当于是Entity(实体),而Component是既包含了组件的数据,也包含了组件的逻辑,这样本身在使用上很方便,也很容易理解,我们通过写不同的脚本继承MonoBehaviour就相当于自己制作组件,然后给不同的GameObject添加不同的组件来让它们拥有不同的功能。而根据我阅读的一些文章和资料里说,这样有一个缺点就是Component与Component之间如果存在耦合的逻辑关系,就会导致底层数据的内存上有很多冗余,造成额外的性能开销。太过底层的理解我目前也还没有彻底明白,不过ECS里就是把原先的Component再度拆分,彻底将逻辑与数据分离,使内存分配更加的合理,提高性能。Entity是一个抽象的对象,它其实只是存储着拥有哪些Component的一个载体,而原来的Component其实是ComponentData,用于存储数据,System里是实际的对不同的Entity进行操作的逻辑。
    上面是我个人在学习了ECS模式之后的一些个人理解,那么接下来说一下Unity自家的这个Entities框架。它目前是在Unity2018.3上面通过PackageManager添加的还属于尝鲜阶段的功能。它提供了一个接口IComponentData是相当于ECS中的C,也就是Component的接口,所有的自己写的Component的struct(注意是用结构体,而不是类)都要实现这个接口,他还有一个ComponentSystem的类,所有我们自己写业务逻辑地方的System的类都要继承自这个类,它里面要包含有一个结构体代表一个组Group,这个Group是相当于把组里面包含的Component的Entity给过滤出来,并注入到这个Group里,而这个Group里应当又一个int类型的Length变量来描述这个组被注入的Entity的数量,另外这个System类还需要我们重写一个OnUpdate的方法,这个方法就类似MonoBehaviour的Update的逐帧回调的方法,用来写我们自己的业务逻辑。比如我自己的demo就是控制一个角色在点击鼠标左键的时候发射大量的子弹,那么我的子弹要移动,按以前的方式我只需要调用类似Transform.Translate的API就可以控制子弹的移动,但是基于ECS模式就不可以,因为Transform的API属于Transform这个接口的,而现在我们基于ECS是没有这些组件来使用的,那么我们就必须自己去写一个让物体向前移动的System,为什么是让物体向前,而不是子弹向前呢?,因为在ECS模式下,我们思考的方式要和以前传统的方式不同,System本身其实是面向全局的,他不会说只作用于子弹的Entity,他会控制所有我们自己过滤的组里的Entity,那么如果我们只想控制子弹的向前移动,就需要我们自己在写Group时注意需要过滤的Component,保证我们注入到这个Group里的只有子弹的Entity,同样的,我们子弹有销毁的需求,那么我们可能还需要写一个子弹销毁的System,同样也要注意定义的Group只把子弹的Entity给过滤完注入进去,System说完了,那么我们还需要创建Entity,我们可以通过World.Active.GetOrCreateManager<EntityManager>()这个API获取到一个叫EntityManager的管理器,然后通过调用这个管理器的Instantiate方法来创建Entity,他传入的参数有两个,一个是Entity的Prefab,前提这个Prefab是Entity,另外一个是用来存放这些Entity的一个NativeArray的对象。这样我们就可以实现创建大量子弹的Entity,然后控制他们向前移动,并经过一段时间销毁了,为了验证ECS和传统方式的性能的区别,我在demo里写了一个开关来控制是使用ECS的方式发射子弹,还是使用传统的方式,这点也是参考了在学习时官方的一个ECS教学视频里的做法,在实际运行过程中发觉效率差别还是很大的,而且我现在使用的方式其实还不是结合了Unity的JobSystem和BurstCompiler的真正意义上的ECS,还夹杂了一些原先的MonoBehaviour的方式,按照官方的说法,将来结合了这两个,效率上会更高。
    最后,我把之前写的这个Demo上传到了我的github上 地址是 https://github.com/FantasyTianyu/UnityECSDemo 有兴趣的朋友也可以去试着checkout出来运行一下看看。

fantasycoding.net 2016-2024 © All rights Reserved京ICP备2020039454号-1