是ECS真的很丑,还是我的用法有问题呢?
godot吧
全部回复
仅看楼主
level 8
旋转的刀 楼主
遵循了ECS的基本规则,E就是纯ID,啥也没有,C就是纯基础数据,啥也没有,S就是纯业务逻辑处理,啥数据也没有。除了E/C/S 之外,还有 EM/CM/SM 三个脚本负责 实体管理、组件管理、系统管理,基本上都是实现一些实例创建、销毁、查询和实例间关系映射的功能(映射还是为了方便查询)
于是就有了一个很尴尬的情况,就是 entity 类作为一个中间桥梁,其实并没有太大的意义,entity 类实例一端关联着真实数据,也就是 component ,另一端关联着界面元素,也就是 Node,当需要通过修改真实数据去触发渲染系统更新界面时,总会需要多次查询,例如:
step1.改变了记录实体当前所在位置的 component 的值;
step2.发送属性值改变的信号;
step3.负责渲染的 system 收到信号后,先要去查一遍是哪些组件改变了值(当然也可以直接用事件参数传递过来),但总需要遍历这些组件,从组件找到实体,再从实体找到界面元素,再去改变界面元素的位置,这一步过于繁琐,至少需要遍历两遍,即使使用稀疏集或者链式调用都改变不了至少需要查询两遍的情况。
我就感觉很丑陋,非常丑陋,请问大家有更好的办法吗?[泪]
2025年02月18日 08点02分 1
level 3
我也在godot用esc,但是用法和你不太一样。 感觉用ecs后,就不应该用观察者模式了,而应该每帧去遍历每个system,把每个entity都在system里执行一次。当然了,里面需要有各种不同的component,有的存数据,有的代表某个状态
2025年02月18日 17点02分 2
轮询的方式感觉好丑啊,有个来源的gd-ecs就是这么写的,我改了三天实在觉得无可救药放弃了,自己重新写了一个。
2025年02月19日 02点02分
我把system分了三类,一类是空闲帧刷新,做一些场景渲染类的处理,也就是你说的那种模式,但是需要加入脏标记。一类是物理帧刷新,做物理计算。还有一个类是纯逻辑和数据处理,只用事件或者信号机制触发。
2025年02月19日 02点02分
level 6
godex好像是个ecs的框架?之前用过。ecs效率的本质是数据连续存储,遍历效率非常高,如果离了这一点那么ecs就是单纯的一种抽象思想了。而且ecs不适合ui,不要用来做界面。
2025年02月19日 02点02分 3
有一个开源的 gd-ecs ,代码写的很丑,我有洁癖看不下去,最后重写了,数据连续存储,内存友好,SIMD 优化等,我觉得在原生 GDS 里基本是做不到的,即使用 SOA + 紧凑数组做到一部分,其实意义也不大,毕竟咱是做游戏,不是做粒子系统、流体系统。除非是能做到像 Arch 框架的 Archetype 和 Chunk 这样
2025年02月19日 04点02分
我觉得ECS本质就是抽象思想啊,最重要的还是能数据行为分离。只是组件连续话的存储方式可以优化缓存使用吧。
2025年02月19日 03点02分
用ECS做UI确实很痛苦,好多难受的事情,逼死精神洁癖和强迫症了[泪]
2025年02月19日 04点02分
@旋转的刀 UI真不要用ecs做
2025年02月19日 05点02分
level 9
我理解,E是最重要的怎么能说没啥意义呢?E里用字典存component,改值的时候,根据key获取改变的component,不需要遍历。
而且ESC是为了拆分数据和逻辑,系统一定会更复杂。这是不可避免的(总要有取舍)
拆分后更灵活,模块化符合单一指责,迭代优化的时候也更方便(都写一起改逻辑的时候很麻烦)
2025年02月19日 03点02分 4
我在知乎上写了好多分析ECS的问题,回复不知道怎么被吃了,等有空了再一起讨论一下哈,我觉得从封装、优雅、执行效率各方面都是矛盾的。
2025年02月19日 04点02分
重新整理了一篇回复,有兴趣可以看一下,我觉得我对于ECS能考虑到的都写进去了,欢迎否正[哈哈] 用数据与逻辑分离的思想制作游戏,遍历和判断实体是否具备某组件这个步骤会浪费算力吗? - 云少的回答 - 知乎 https://www.zhihu.com/question/5816923133/answer/104879576118
2025年02月19日 08点02分
@旋转的刀 我其实反而觉得,真正的痛点是ECS不完全符合godot“节点-场景”的设计,很多东西比如AnimationTree就是组件,真和ECS一起用是有点不伦不类的
2025年02月19日 13点02分
@Bzio 今天有了一点新的收获,尝试把界面的东西丢给界面去负责了,ECS部分就专心负责数据和逻辑处理了,虽然性能上略有损失,但是这样子起码自己心里舒服多了,对于开发效率也有提升,解耦之后方便多人协作。
2025年02月20日 15点02分
level 7
没有银弹。
2025年02月19日 03点02分 5

2025年02月19日 04点02分
level 1
我没看过这些规范。按照我个人的开发体验来看,就是需要实体字典。godot对象只有一个实体其它都是引用,可以很方便的用数据记录对象。
2025年02月19日 05点02分 6
数组记录对象
2025年02月19日 05点02分
是这么做的,但是很方便不是很认可。我刚在知乎上写了一篇回答,把我对ECS框架的全部理解都写进去了,欢迎否正[哈哈] 用数据与逻辑分离的思想制作游戏,遍历和判断实体是否具备某组件这个步骤会浪费算力吗? - 云少的回答 - 知乎 https://www.zhihu.com/question/5816923133/answer/104879576118
2025年02月19日 08点02分
@旋转的刀 很遗憾我的注意力不是很集中,只能粗略的看。我是刚开始尝试完全开发较大的项目。目前我通过文档记录接口与逻辑,重构了很多逻辑方法。之前我只记录类型,因为name是浮动的,但是最近我开始直接引用实例了,因为我想通了记录的方法。
2025年02月19日 09点02分
@旋转的刀 我还是面向对象的架构,但是godot的group给了我新的想法,让我能给对象序列化的标签并记录,也可以考虑写死对象的name。对象和数据分离在我来看是有点多余的。
2025年02月19日 09点02分
level 1
数据主要还是加载与保存的时候最重要,重要的是理清需要静态保存的数据在运行时的逻辑关系。
2025年02月19日 05点02分 7
如果运行时的对象不便保存,可以记录对象名字,在加载时放入等待组装队列直到对应的对象被组装再赋值。
2025年02月19日 05点02分
level 1
总之根据引擎特性,godot允许实例数组的存在且可以通过自带的查询查找实例。如果你将每一类对象单独保存到数组也可以快速搜索到目标对象。
2025年02月19日 05点02分 8
level 1
需要模数分离的地方应该是需要严格监管数据的。可能伴随有复杂的权限记录与回档机制。
2025年02月19日 05点02分 9
level 1
喜欢ecs用bevy
2025年02月19日 05点02分 10
还喜欢用gds[勉强]
2025年02月19日 08点02分
1