至少割草(塔防都算吧)这种抠性能的游戏我是不太敢用
不消耗,割草性能会更高
啥原理?1234
ECS框架和Cocos Creator使用了不同的导入路径,所以用法上完全没有影响
import { Component as CocosComponent, _decorator } from 'cc';
import { Component as ECSComponent } from '@esengine/ecs-framework';
几个问题我一起回答把,性能上一定比传统开发是要好的
1. 批量处理 > 逐个处理
传统游戏开发是每个敌人单独调用update(),函数调用开销巨大,但是ECS做法一个MovementSystem处理1000个敌人,循环开销几乎为0,游戏1000个单位,ECS比传统方式快5倍以上
2. 智能缓存 > 重复计算
框架有位掩码缓存、查询结果缓存、原型系统缓存, 组件查询从O(n)降到O(1), 并且对象池避免频繁new/delete,割草游戏就算10000个敌人依然60fps稳定,瓶颈完全在你的渲染性能上。
3. 按需计算 > 全量更新
一般正常游戏所有对象每帧都要检查所有逻辑,而 ECS做法只有包含特定组件的实体才参与特定系统,1000个敌人,只有200个在移动?只会处理200个
没有demo吗
赞!求一个Cocos的Demo
我已经买了插件啦
传统写法
// 最开始认为的代码
class Enemy {
isDead = false;
}
// 实际项目3个月后
class Enemy {
isDead = false;
isPlayingDeathAnim = false;
deathAnimTime = 0;
deathEffectType = "explosion";
hasPlayedDeathEffect = false;
canRevive = true;
reviveTime = 5.0;
isReviving = false;
deathCause = "";
killerPlayerId = -1;
update(deltaTime) {
// 一堆复杂的if-else逻辑
if (this.isDead && !this.isPlayingDeathAnim && !this.hasPlayedDeathEffect) {
this.startDeathAnimation();
this.playDeathEffect();
this.hasPlayedDeathEffect = true;
}
if (this.isPlayingDeathAnim) {
this.deathAnimTime += deltaTime;
if (this.deathAnimTime > 2.0) {
this.isPlayingDeathAnim = false;
if (this.canRevive) {
this.startReviveCountdown();
} else {
this.destroy();
}
}
}
// ... 更多复杂逻辑
}
}
ECS写法
class DeadComponent extends Component {
deathTime = Time.totalTime;
cause = "";
killerPlayerId = -1;
}
class DeathAnimationComponent extends Component {
effectType = "explosion";
duration = 2.0;
currentTime = 0;
hasPlayedEffect = false;
}
class RevivableComponent extends Component {
reviveTime = 5.0;
canRevive = true;
}
// 系统:专门处理一种逻辑
class DeathAnimationSystem extends EntitySystem {
process(entities) {
// 只处理正在播放死亡动画的实体
for (const entity of entities) {
const anim = entity.getComponent(DeathAnimationComponent);
anim.currentTime += Time.deltaTime;
if (anim.currentTime >= anim.duration) {
entity.removeComponent(DeathAnimationComponent);
if (!entity.hasComponent(RevivableComponent)) {
entity.destroy();
}
}
}
}
}
class ReviveSystem extends EntitySystem {
process(entities) {
// 只处理可复活的死亡实体
for (const entity of entities) {
const revive = entity.getComponent(RevivableComponent);
revive.reviveTime -= Time.deltaTime;
if (revive.reviveTime <= 0) {
entity.removeComponent(DeadComponent);
entity.removeComponent(RevivableComponent);
entity.addComponent(new HealthComponent(100));
}
}
}
}
传统方式的问题
- 所有逻辑混在一个update()里:每个敌人每帧都要检查所有状态
- 无法按需处理:死了的敌人还在检查移动逻辑,活着的敌人还在检查复活逻辑
- 扩展困难:新增一种死亡效果,要改Enemy类的update方法
ECS的优势
- 按需处理:只有正在播放死亡动画的实体才进入DeathAnimationSystem
- 职责分离:死亡动画逻辑和复活逻辑完全独立
- 性能更好:1000个敌人,可能只有50个在播放死亡动画,只处理这50个
添加新死亡效果:
-
传统方式: 修改Enemy类的update方法,增加新的if-else分支
-
ECS方式: 新增PoisonDeathComponent + PoisonDeathSystem,不动现有代码
ECS不是组件更少,而是逻辑更清晰,性能更好。组件多一点不是问题,关键是避免了"所有实体每帧检查所有逻辑"的性能杀手
塔防、割草游戏正是ECS的强项,大量同类对象是ECS最擅长优化的场景。
已购买,支持
购买支持一下,等下个项目再试试好用不
感谢各位支持,最近也会写一个类割草的demo,这两天忙着结婚婚宴来不及回复
新婚快乐

更想你出个插件开发教程 
ECS结合一下行为树?
这个已经在做了,已经结合了一部分
看你帖子标记的是creator2.x的。结果进去是3.8.6以上的哈。
还没研究过ecs模式的开发。unity之前看过别人用过。但总感觉挺麻烦的一直没用。
论坛里没找到可以发布3.x的插件的位置所在发在这了,商店里写了正确的版本要求3.8.6的,因为考虑到了易用性所以没有和unity架构一样,他们那个写起来确实很不舒服,我也不太喜欢unity的ecs那套,可以看一下文档的示例,写法还是很好懂的 
橘子大佬,这个一定要继承 Component 吗?
我想结合fairygui一起开发的话能用上么?不打算使用cocos原本的ui来开发。但看到你例子上都是继承Component的。
然后都是通过getComponent和addComponent来获取组件。那么我继承使用的话是否就不可以了?

