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

大佬牛逼。Mask一下

还是可以用的,就是需要你做一层适配包装一下,这是我提供的一个思路可以参考一下

class FairyGUIComponent extends Component {
    private fairyUIObject: any;
    
    constructor(
        private packageName: string, 
        private componentName: string
    ) {
        super();
    }
    
    onAddedToEntity(): void {
        super.onAddedToEntity();
        // 创建FairyGUI对象
        this.fairyUIObject = fgui.UIPackage.createObject(this.packageName, this.componentName);
        fgui.GRoot.inst.addChild(this.fairyUIObject);
    }
    
    onRemovedFromEntity(): void {
        if (this.fairyUIObject) {
            this.fairyUIObject.removeFromParent();
        }
        super.onRemovedFromEntity();
    }
    
    // 提供FairyGUI的所有功能
    public getFairyObject(): any {
        return this.fairyUIObject;
    }
    
    public setText(childName: string, text: string): void {
        const child = this.fairyUIObject?.getChild(childName);
        if (child) child.text = text;
    }
    
    public setVisible(visible: boolean): void {
        if (this.fairyUIObject) {
            this.fairyUIObject.visible = visible;
        }
    }
}

我这里只是提供一层思路哈,但是具体怎么使用还得具体按照api来使用,而且其实我不太推荐ecs用于ui上的,ui上用mvc或者其他的方式可能会比较好一些,场景里的使用的ecs比较好,因为这个框架设计出来主要为了解决场景中大量相同组件的实体的优化。ui上可能就失去这个优势,并且只是复杂你的ui写法了

如果一定用到ui上,你的游戏里以后写代码都要这么写了,所以你要自己抉择是否要这么用哈

class PlayerUIComponent extends Component {
    private healthBar: any;
    private nameLabel: any;
    private skillPanel: any;
    
    constructor() {
        super();
    }
    
    onAddedToEntity(): void {
        super.onAddedToEntity();
        
        this.healthBar = fgui.UIPackage.createObject("GameUI", "HealthBar");
        this.nameLabel = fgui.UIPackage.createObject("GameUI", "NameLabel");
        this.skillPanel = fgui.UIPackage.createObject("GameUI", "SkillPanel");
        
        fgui.GRoot.inst.addChild(this.healthBar);
        fgui.GRoot.inst.addChild(this.nameLabel);
        fgui.GRoot.inst.addChild(this.skillPanel);
        
        this.healthBar.setXY(10, 10);
        this.nameLabel.setXY(10, 50);
        this.skillPanel.setXY(10, 100);
    }
    
    public updateHealth(current: number, max: number): void {
        if (this.healthBar) {
            const progressBar = this.healthBar.getChild("progress");
            progressBar.value = (current / max) * 100;
        }
    }
    
    public setPlayerName(name: string): void {
        if (this.nameLabel) {
            this.nameLabel.text = name;
        }
    }
}

class PlayerUISystem extends EntitySystem {
    constructor() {
        super(Matcher.empty().all(PlayerUIComponent, HealthComponent));
    }
    
    processEntity(entity: Entity): void {
        const ui = entity.getComponent(PlayerUIComponent);
        const health = entity.getComponent(HealthComponent);
        
        ui.updateHealth(health.currentHealth, health.maxHealth);
    }
}

const player = scene.createEntity("Player");
player.addComponent(new HealthComponent(100));
player.addComponent(new PlayerUIComponent());

scene.addSystem(new PlayerUISystem());

哦哦。这样啊。我以为是整个项目都是用ecs开发呢。推荐用只是场景上的而已啊?

是的,ECS框架主要是针对游戏场景逻辑设计的,不是整个项目都用ECS,ECS擅长处理大量相似对象的复杂交互(比如100个敌人同时AI、移动、战斗),但UI更多是单个界面的状态管理和用户交互,用传统的MVC反而更简单直接

场景里的事件(比如玩家血量变化、获得道具)通过事件系统通知UI更新,UI的操作(比如点击技能按钮)也通过事件通知游戏场景执行。

这样既能享受ECS在游戏逻辑上的优势,又保持UI开发的简洁性,是目前比较成熟的架构方案

1赞

不明觉厉。已买,以后有需要再看哈。。。

请问有demo可以看下吗

demo还在写哦,最近尽量再抽时间写这个,可以看文档先学习下

ecs插件v1.0.4更新(框架版本要求v2.1.24)

  • 修复因为组件属性过大导致的性能问题
  • 修复因组件内循环引用导致的调试卡死问题
  • 优化调试面板内组件属性(修改为延迟加载)
  • 实体面板需要点击刷新才能刷新查看当前帧的实体
  • 修复点击实体导致的编辑器警告问题
  • 移除热更新链接失败错误提示

插件地址:cocos-ecs-framework

求个Cocos Demo

这两天再写哦,会写一个割草的demo的,可以加群哦,到时候写好了群里会通知源码链接的

你的文档真的详细,太牛逼了!
我现在想要Demo的主是因为我不太明白,这个框架和Cocos的Prefab机制 是如何结合的

其实区别不大的

传统加载方式

resources.load("prefabs/Player", Prefab, (err, prefab) => {
    const playerNode = instantiate(prefab);
    this.node.addChild(playerNode);
    playerNode.setPosition(100, 200);
});

ecs里是这么操作的

export class GameScene extends Scene {
    
    private async createPlayer() {
        const entity = this.createEntity("Player");
        entity.addComponent(new Transform());
        
        const nodeComp = entity.addComponent(new NodeComponent());
        nodeComp.node = await SimplePrefabFactory.createUnit("Player");
    }
}

export class SimplePrefabFactory {
    /**
     * 通过预制体路径创建单位
     */
    static async createUnit(unitType: string): Promise<Node> {
        const prefabPath = `prefabs/units/${unitType}`;
        
        return new Promise((resolve, reject) => {
            resources.load(prefabPath, Prefab, (err, prefab) => {
                if (err) {
                    console.error(`加载预制体失败: ${prefabPath}`, err);
                    reject(err);
                    return;
                }
                
                const unitNode = instantiate(prefab);
                unitNode.name = `${unitType}_${Date.now()}`;
                resolve(unitNode);
            });
        });
    }
}

以后就直接系统里操作对应的NodeComponent里的node就可以了

割草项目上传了,有兴趣学习的小伙伴可以下载下来使用3.8.6版本运行

esengine/lawn-mower-demo

2赞

可以指定 entity component 做快照吗?

目前没写快照功能,这两天正在计划做这个支持,可以加群到时候提交pr后会再群里通知的

大佬 想问下 这个可以搭配xforge框架使用嘛 新人 不太懂这个

看着不错,先买了,周末慢慢看。

可以的,完全不冲突,xforge对目录结构有规范,别用这个的 项目模板生成, 按照xforge的规范放文件就好

好的 哥 感谢

确实专业 :love_you_gesture: :love_you_gesture: :love_you_gesture:

1赞