【ECS框架】专业级游戏架构 + 可视化调试插件,5年持续更新!附完整教程

有人已经用上了吗?谈谈使用感受不?我看评论区有写Xfoorge加这个,实际情况是怎么样的

哥们儿,你的文档是不是该更新了? 复制你文档代码到工程中,一片片的报错,不是变量名变了,就是接口已经没有了。

不好意思,最新的更新了,以github文档为准,有问题可以加群反馈哦,这里有时候看的不及时

战术mark

在JS上构建ECS,JS没有强内存管理,Cpu的Cache内存连续性带来的性能提升根本发挥不出来,不懂在JS上构建ECS的意义在哪里?

一个0.0000001秒的1000次调用,你优化10倍性能是毫无意义的。您这里列出的性能提升,如果有数据测试,欢迎举证。

如果只是为了简化开发,更应该考虑的是自己的OOP基础是不是扎实?而不是回退到面向函数编程。据我这么多年的观察,真的懂OOP的前端开发,不足5%

关于你说的这几个观点再实际游戏开发里,每帧只有16.67ms的预算下,哪怕再微小的优化累积效应也是显著的,而且目前再js中ecs的价值不在于性能,更在于可维护的架构。

还有soa和传统存储的对比测试我已经有写过单元test,同样的案例确实能带来一定的性能提升,具体测试代码都在源项目里。

关于你说的oop和ecs这是两个不同的设计理念,一个是数据驱动设计,将数据和行为分离,并且组合优于继承,能够避免深层继承树的复杂性,虽然没有内存控制,但是可以通过typearray等技术仍然可以获取可观的性能提升

很多人认为ecs主要的作用是提升性能
但其实性能真的没那么重要,最关键的是组合,这才是他最最重要的东西

1、每帧16.67ms那只是渲染帧的时间,逻辑帧一般采用20-30帧。所有它不是16.7是33.3或者50ms。

2、纯代码逻辑,我用OOP的情况下,同屏200个单位,有寻路,有碰撞检测,性能占比20%-30%。

纯CPU运算下,如果你存在CPU缓存的命中策略,性能是会有巨大提升,这也是ECS的唯一优势。但JS语言类似Java的GC机制,显然做不到这一点。纯逻辑代码,值得优化的点只有数据结构,其他都是没有任何性价比的事。
性能优化,应该基于当前性能瓶颈去做,而不是想当然的觉得少一次Update就叫优化。另外一个1秒的调用,优化到0.1秒是有意义的,一个0.00001毫秒的东西优化到0.000001毫秒是没有意义的。虽然这两样都叫优化了10倍。当然,从你一个程序员的角度这可以是你的KPI,但我从一个主程的角度,这是没有任何性价比的事。

3、面向数据编程,就是面向过程编程,这本就是一种设计模式的倒退。很多人觉得这种模式更好,那是因为压根就没掌握OOP。没有更高层的抽象和封装,开发效率比OOP要慢的多的多。
而OOP不等于放弃了组合,EntityComponent本来就是OOP里的概念。
至于什么时候用组合什么时候用继承,OOP的书第一章就写了,has a 和is a的区别。前者用组合,后者用继承。而继承本身是一种非常严格的定义,很多人用不好OOP,就是因为错把has a当继承来用。

你说得对,逻辑帧通常是 20-30fps。但这更说明了我的观点 - 在 33.3ms
的预算内,哪怕是几毫秒的优化在大规模场景下都是有意义的。我的测试显示
,20000 个实体的批量更新,SoA 能节省 32ms(46.90ms vs
14.63ms),这在逻辑帧预算中就很可观了

而且 我也同意应该基于实际瓶颈优化。但我再测试数据显示,在特定场景下(大规模批量
操作),ECS + SoA 确实能带来显著提升。你提到的"200个单位 20-30%
CPU",如果换成 20000 个单位做批量物理更新,差异就会很明显

除了性能,ECS 的核心价值确实在于架构。数据驱动设计让系统之间解耦,组
合优于继承避免了深层继承树。这不是 OOP的倒退,而是针对特定领域(游戏中大量同质实体)的设计模式选择,而且我的框架设计是混合式的 - 可以选择性启用SoA。小规模随机访问用传统存储,大规模批量操作用SoA。这样既避免了不必要的开销,又能在需要时获得性能提升。

ECS 在 JS 中的价值不是万能的性能银弹,而是在特定场景下的有效工具。我的测试数据也只是证明了在合适的场景下确实有显著收益

OOP vs ECS这个话题我们已经讨论够了,观点都表达清楚了。我不想再纠结这个问题,各自用各自认为合适的技术方案就行

2赞

没有连续内存的优势后,都不考虑内存连续布局,会发现oop与这个也不是硬冲突的,这个能帮助你更好的组合和调度,数据与逻辑分离的更彻底,

能不能用webassembly来弥补JavaScript的强内存管理上的短板? :thinking:

或者JavaScript不是有ArrayBuffer吗?它的内存不是连续的吗?用ArrayBuffer弥补JavaScript的强内存的短板?我想问 :thinking:

你对象是new出来的,分配的内存不受你的控制

@南城su 发现微信开发者工具中,entitySystem获取到的entities的类型为一个数组,只有一个元素,而且元素类型为Set
而浏览器中就是正常的,是一个entities数组。
怎么办?

mark!!

更新到最新版本就可以解决了,新版本解决这个问题了

谢谢大佬1小时搞定

mark一下!!

ECS框架更新v2.1.45

  1. 新增World概念(支持多个World管理多个Scene)
    文档: ecs-framework/docs/scene-management-guide.md at master · esengine/ecs-framework

单场景迁移指南(不影响现有单场景功能仍可使用)

// 原始单Scene代码
const scene = new Scene();
Core.setScene(scene);

// 迁移到World模式(可选)
Core.enableWorldManager();
const world = Core.getWorldManager().createWorld('MainWorld');
const scene = world.createScene('main', new Scene());
world.start();
world.setSceneActive('main', true);

注意:原scene属性set索引器已移除,请更改为setScene方法避免上下文丢失问题

  1. 优化内部索引机制(移除bitmap/hash/sorted等索引类型更改为SparseSet索引减少切换索引开销)
  2. SOA存储器新增多个安全方法 getTypedFieldArray/getEntityIndex/getEntityIdByIndex
1赞

写了大半年的ecs多人同步割草游戏,前后端用同一套代码,尝试过状态同步、状态+帧同步、纯帧同步。

ecs优点就是:

每种方案都可以通过不同系统之间的组合方向实现功能

策划想怎么改都行,功能改动灵活不受代码复杂度的影响,想改功能就改改系统和组件组合就行,代码逻辑松散解耦

用ecs旧项目改成新项目很快,改改组合

缺点:

代码逻辑松散解耦,实现一个功能要分几个系统和文件,导致新人比较难上手你的代码,需要新人先理解框架大致整体流程再看细节

由于功能要分几个系统和文件,调试起来麻烦,比较难跟踪同个实例,这需要另外写调试工具

由于系统组一帧内只能按顺序执行,在有些情况下需要递归处理的逻辑不好处理,比如 角色攻击 buff效果后又产生buff, buff后面的系统产生的buff可能要等下一帧再执行等…解决类似问题没有传统写法那么轻松

某些情况下性能没传统写法好,很多时候要用传统写法+ecs写法解决类似问题

对比cocos那种功能组件写法,优点在于

实体和组件写好后基本不用动,改业务逻辑大部分只改系统那部分文件
比如前后端共用一个实体和组件(属性),前后端有各自系统组合(逻辑)实现具体功能

对于没用过ECS项目人来说,上手是有点难得

3赞