谈论什么
这里我主要从工程或设计的角度讨论, 至于ecs对性能的优化方面
的事情我这不做过多介绍.
为什么要把ec系统里的c分为coponent与system两快
ecs系统的优点
ecs系统的缺点
从编程演化看ecs系统
ecs总结
吐槽一下unity 的ecs系统
为什么要把c与s分开
这是我在用ecs系统时最大的一个问题,现将我的一点想法与大家分享
原因在于将c与s分开之后,就可以降低逻辑之间的关系,极大的降低系统复杂度
原理如下:
当system(逻辑)需要其他数据,直接找到entity好了,数据都在上面。
没有必要与其他system(逻辑)有关联
所有的关联都在entity及其component上
在拓扑关系里,若将所有entity看成一个节点,那么所有system都依赖这个
节点,而且entity与compoent又不依赖system,这样一个星形的单方向的拓扑结构
极大的简化了系统的之间的关系与复杂度。
下面讲的优点都在这基础上具体的表现。
ecs系统的优点
- 规则简单易于推广
只有component能存数据,只有system能有行为, entity结构永远不变
规则就这么简单,比较容易记住
- 降低了复杂度
由于ecs系统的所有操作都是对entity内的数据(Component)的直接修改
因此大大的降低了不确定性与花费的 精力
举例: 系统庞大之后, 做一个系统或功能可能要依赖好几个系统
用面向对象或ec系统的时候,你可能需要调
用一些函数
而这些函数有可能代价很高很复杂, 比如内部调用的文件存储、
网络、渲染api这类复杂的操作,需要很小心的调用
不然很可能就会有性能问题。
而在ecs系统中即便是调用的辅助函数, 本质都是对数据的操作
能够很方容易估算出调用的代价,而且代价也相对较小。
- 不需要缓存机制
正因为ecs创建entity代价小,
创建对象直接生产,不需要内存池对象池也相应减少了代码复杂性
- 容易写出好的代码
由于ecs系统强制把数据和行为分开了, 写逻辑的程序就不容易出错了。
因为本质上写的东西就是对纯数据的操作。
规范更容易推进, system里面不保存任何数据, 规则也很清晰,容易执行
- 统一数据的存放方式
需要记录的东西都使用component来记录
这样大家就不会出现数据存储在一些奇怪的地方
- 统一了数据的获取方式
原有的方式,每个系统的调用, 需要用到的数据可能有各种获取方式
比如调用某个或多个方法来获取。
而ecs系统则统一使用类型的组合作为数据的获取条件
- 二进制友好
游戏中常需要保存游戏进度, 或是同步数据给服务器。
ecs系统里只要把特定的component筛选出来序列化就可以, 非常方便
- 降低了代码间的耦合
所有的system 可以做到只依赖 相应的component
直接的交互也使用component来进行, 这样就极大的降低了代码间的耦合
ecs系统缺点
- 模块独立性不强与系统强关联
一些功能的重用必须要有整个ecs环境才能运作, 模块独立性不高
一些底层功能, 如网络,文件操作使用ecs就不好做封装
- 模块间无法隐藏数据
正因为模块间无法隐藏数据, 导致一个问题就是设计不好的数据会影响所有系统
对写的不好的代码容忍度比较低
- 无法统一编程模型, 只能解决特定问题
无法像ec系统, 比如com组件那样将所有的代码都用一套来封装
- 新的思考模型
新的编程模型需要新的思考方式,大家需要习惯一下
- 对异步处理支持不好
编程演化
-
01编程
- 有就行了, 要求不要那么高
-
汇编
- 人类容易记住字母的命令,而不是01的数字
-
c语言
- 演化为数据结构与算法, 因为发现代码通常不会改变。
这样把结构与算法分开更加容易写出健壮的代码,
代价是不能在运行时通过动态修改代码获得最高的性能
- 演化为数据结构与算法, 因为发现代码通常不会改变。
-
oop 初代
- 人类对事物的认知本来就是对对象进行分类来思考的
oop能降低大家的思考难度,而且可以将垃圾代码隐藏起来
代价是性能有所降低
- 人类对事物的认知本来就是对对象进行分类来思考的
-
oop ec编程
- 在自然的环境下分类思考是可行的, 因为类都是不变的
但在游戏里的类是会变的啊, 通过配置加个类型跟玩似的
于是就强调面向行为
具体做法是限制 类的继承,只使用组合。强调设计接口的不变。
- 在自然的环境下分类思考是可行的, 因为类都是不变的
-
oop ecs编程
- 系统之间关系太复杂,性能要求也有所需要。
通过限制编程的方式,逻辑上只对数据进行操作
达到简化系统,降低大家对系统的理解成本,降低对逻辑编程的要求
基本编程方式的发展就是各种简化
一种是将编程方式与人类思考方式靠近, 简化理解的成本,简化编程的难度.(设计一门新语言)
一种是通过对已有编程方式的限制,简化系统的复杂度,出错的可能。(编码规范)
ecs系统总结
ecs的最大收益的,其实是做逻辑的程序,可以更加容易的写出优秀的代码。
ecs系统在我看来就是ec系统的一个子集,在ec系统上加上一些
限制条件容易做成一个ecs系统,ecs系统的好处是我们能够
更加容易的写出高质量的代码。
由于ecs的局限性, 主要用于上层架构, 不会用于底层架构
至于在ecs中需要调用到的外部api,通常都会在ecs中加个中间层并入已有的ecs系统中
比如要做网络同步, 就需要创间一个网络相关的system,再把数据同步出去
吐槽一下unity 的ecs系统
unity 的ecs系统更多是在性能上的优化方便上的便利,而不是保持ecs本身的简单化
-
unity ecs系统本身弄的复杂, 复杂在下面几个方面
unity 内部隐藏了太多细节
隐藏了入口, 不方便从整体上来学习了解
-
使用来太多attribute, 还有特定结构来实现基础功能
比如system 之间的调用次序
正由于unity ecs系统过于复杂, 导致无法直接将逻辑代码拷贝到服务器