Unity ECS 框架
< 返回列表时间: 2018-03-22来源:OSCHINA
20180312
ECS编程思想
这种编程思想很早前就已经提出,ECS分别是Entity,Component,System的缩写. Entity是实例,作为承载组件的载体,也是框架中维护对象的实体. Component只包含数据,具备这个组件便具有这个功能. System作为逻辑维护,维护对应的组件执行相关操作.
ECS和传统的OOP相比更看重的是组件,附加组件即具备功能.
C#是面向对象语言,从语言层面上就支持面向对象的编程思想:集成封装和多态. 面向对象:我是什么,我有属性,我有方法,我要继承然后重写成自己独有的. 面向组件:我有什么,我有组件便具备这个功能,我由很多组件组成了实体.
按照ECS的思路,功能拆分成组件,然后把这些细小的组件组合便组成了具备所需功能的对象.实际上Unity也是这种实现思路,但是它的组件式属性和逻辑的合集.
最近看了ECS编程思想,看了Entitas逻辑,写了小Demo,感觉:
编程思路/框架没有最好只有更合适,可能A框架适合RPG游戏,B框架更适合FPS游戏. Entity的时序
开发中经常会遇到控制时序的逻辑,比如某个Entity必须在另一个Entity逻辑完成后再执行,当然可以通过添加组件标识来控制时序执行,但是如果存在大量这种逻辑势必会增加很多对应的组件作为标识. System时序
同样可以添加Component作为控制标识作为过滤条件,A系统要在B系统结束之后,C系统启动之前,D系统挂起时...开发到后期怎么办.(待机,前摇,蓄能,施法,表现,结束,)太多太多状态一帧/分帧维护起来估计也会乱吧. System更合适维护一组Entity 比如FPS游戏,MOBA游戏用ECS思想拆分合适,每个玩家的角色功能对等(都是人物,都在移动,战斗)不同的角色的技能枪支拆分单独实现. 如果是大型RPG游戏,每个门派角色,大厅npc,商城商人,敌人角色的状态动作各不相同,这种ECS当然能实现,每个功能,拆分成细小组件,创建对应System类维护,但是这样归根到底一个System经过遍历筛选其实只维护了一个Entity上面的组件.因为角色功能独有,以后这个组件也不会被其他Entity组合使用. 功能解耦
功能之间解耦,对应的组件和系统只关心本身的功能,不会对其他功能造成影响. 重构
不方便重构 数据维护
数据分散到对应的组件,比如服务器下发一份最新数据,需要一一维护对应组件的属性,数据收集也是如此. 客户端服务器共享代码
客户端拆分表现组件后,只包含纯逻辑功能. 数据层表现层分离
在不同的组件和系统中维护,不必像oop再拆分表现逻辑. 方便扩展
如果设计合理,可以通过现有组件组合新的Entity. 1- 性能
数据在内存中线性存在,Entity复用.
ECS框架:Entitas
基于ECS的框架有很多,Entitas便是其中一个.
官方的ECS也会在2018.1beta版本中推出.
根据wiki很容易就能够搭建起项目,运行起工程,但是有些也需要开发者注意,比如Component作为标识还是作为数据存储;Component生成代码后改变类型或者删除字段后的生成报错,Group/Feature/Unit使用等等.
关于代码生成,它提供两个版本: 免费版 收费版
免费版根据反射生成代码,需要无编译错误下运行;收费版不需要,即使有代码报错也可以生成代码.
自己扩展的代码可以分为两部分: Components 其他代码(System,Service...等其他逻辑)
这样做的好处是重新生成代码时,方便的把这两个目录移除项目(或者StreamingAssets),生成基础代码,然后移回Component代码,然后生成组件代码,然后移回其他代码.
Entitas实践
最简单的输出hello world
源码: https://github.com/hiramtan/test/tree/Entitas_Example_HelloWorld
创建一个Component: public class HelloWorldComponent : IComponent { public string s; }
生成代码后创建两个system,一个用来创建entity并附加组件,另一个用来输出日志: public class CreatSystem : IInitializeSystem { private Contexts _contexts; public CreatSystem(Contexts contexts) { _contexts = contexts; } public void Initialize() { var e = _contexts.game.CreateEntity(); e.AddHelloWorld("hello world"); } } public class HelloWorldSystem : ReactiveSystem<GameEntity> { private Contexts _contexts; public HelloWorldSystem(Contexts contexts) : base(contexts.game){ } protected override ICollector<GameEntity> GetTrigger(IContext<GameEntity> context) { return context.CreateCollector(GameMatcher.HelloWorld); } protected override bool Filter(GameEntity entity) { return entity.hasHelloWorld; } protected override void Execute(List<GameEntity> entities) { foreach (var e in entities) { Debug.Log(e.helloWorld.s); } } }
上面的代码已经实现了输出功能,但是为了方便管理上面的这两个System,我们添加一个RootSystems专门管理游戏中的各种System: public class RootSystems : Feature { public RootSystems(Contexts contexts) { Add(new CreatSystem(contexts)); Add(new HelloWorldSystem(contexts)); } }
所有的功能都实现了,在unity工程中添加一个入口方法挂载到场景中,Main.cs: public class Main : MonoBehaviour { private RootSystems s; // Use this for initialization void Start() { s = new RootSystems(Contexts.sharedInstance); s.Initialize(); } // Update is called once per frame void Update() { s.Execute(); } }
运行,正常输出,因为输出实现的是reactivesystem,当值发生变化时便会输出.
Unity ECS
今天untiy在beta版本中公布了自己的ECS系统,Entity,ComponentData,ComponentSystem,随着unity官方的引入,势必会被推广起来.
点击链接加入QQ群【83596104】: https://jq.qq.com/?_wv=1027&k=5l6rZEr
参考资料 https://github.com/sschmid/Entitas-CSharp https://blog.codingnow.com/2017/06/overwatch_ecs.html http://www.ecsframework.com/ https://youtu.be/OJmVBo5HGOY http://t-machine.org/index.php/category/entity-systems/ http://www.benmutou.com/archives/2421 https://www.cnblogs.com/yangrouchuan/p/7436533.html http://blog.csdn.net/u012632851/article/details/75370836 http://blog.csdn.net/langresser_king/article/details/46324977 http://blog.csdn.net/wuxiaoming1733/article/details/79037812 http://blog.lmorchard.com/2013/11/27/entity-component-system/ http://piemaster.net/2011/07/entity-component-primer/ http://www.richardlord.net/blog/ecs/what-is-an-entity-framework.html http://blog.csdn.net/qq992817263/article/details/78155443
热门排行