[Cocos 参赛插件][godxkey] 自动绑定指定资源到组件代码内 (优惠中)

[Cocos 参赛插件][godxkey] 自动绑定指定资源到组件代码内 (优惠中)

image

蓝色的链接都是可以点击的

我正在参加 Cocos 社区开箱即用插件征集赛,
我的作品是《[godxkey] 自动绑定指定资源到组件代码内》,
作品链接:如下
https://store.cocos.com/app/detail/4009

[godxkey] 自动绑定指定资源到组件代码内 | Cocos Store

开发环境

  • 引擎版本:Cocos Creator 3.4.0
  • 编程语言:Javascript + Typescript

技术介绍

  • 1.本插件所有内容都不加密 (以供大家研究)
  • 2.就是想着能快速查看和用代码来绑定资源, 省点力气 (替代手动拖动资源来绑定到代码组件上)
  • 3.可以把查询到的资源导出为 JSON 文件, 方便后续更多的操作, 免去手动拖动的繁琐
  • 4.可用于多个关卡预制体的多个资源进行自动绑定 (Auto Bind)
  • 5.如果有资源绑定关系丢失, 可以启动代码, 自会自动绑定, 无需手动寻找和绑定
  • 6.插件的菜单栏做了个简单的多语言 i18n 的支持

痛点解决

  • 1.支持自定义目录查询资源, 支持选中查询资源
  • 2.支持查询到资源后, 导出相关的资源信息为 JSON 文件, 可根据 JSON 文件来绑定相关资源
  • 3.支持格式化 JSON 文件, 支持 AES crypto-js 加解密字符串, 可自定义秘钥
  • 4.在场景代码面板上, 勾选相关选项即可进行绑定资源, 可视化操作, 相关操作有对应提示
  • 5.目前已支持查询和绑定 .prefab , .mp3 , .jpg , .png 的资源 (其它类型的可以参考代码来改造)

目前已测试平台

  • Cocos Creator 3.4.0
  • Cocos Creator 3.5.2
  • Cocos Creator 3.6.0

目前主要的 TS 代码共计 (1486行, 内部写有较多注释)

使用方法 + 功能演示

1.1 手动扫描并启动资源绑定插件

1.2 调整编辑器语言,查看中英文版本的插件显示

1.3 导入资源绑定组件节点到场景内支持快捷键 (Ctrl+Alt+I)

2.1 查询指定目录下的资源,绑定到组件面板上,并导出为 JSON 文件

2.2 指定查询 internal 目录下的资源, 并选中已查询到的指定类型的资源

3.1 绑定非插件内的 JSON 文件插件内的已锁定, 格式化 JSON 文件

3.2 请注意, 上锁的插件内的 JSON 不允许格式化, 建议在 assets 文件夹内操作

4. 加解密文件路径的字符串请注意秘钥要保持一致 8 ,16 , 32 位 , 秘钥可以用中文 (目前秘钥内放置了零宽字符)

5. 绑定插件内的示例 JSON 文件, 选中绑定预制体选项, 查看效果

6.1 根据插件内的 JSON 文件来绑定指定 Mp3 和 Sprite 图片资源

6.2 采用之前生成的 assets 文件夹下的 JSON 文件来绑定资源

6.3 添加日志(非编辑器环境的提示)

关于 Vscode 和 零宽字符

Alt+z 可以切换 Vscode 的代码是否自动换行,
JSON 文件自动保存时,让 Vscode 不格式化, ctrl+k ctrl+shift+s 快捷键,
Vscode内可设置= renderControlCharacters + renderWhitespace 来查看一丝零宽字符的踪迹

  • 零宽字符如下

本插件的目录结构(内置一些个人思路)

(插件文件夹-代码+资源目录)
cc-auto-bind-res_3_x>tree /f
卷 Data 的文件夹 PATH 列表
卷序列号为 EC23-3D55
D:.
│  main.js (插件主代码)
│  package.json (插件配置文件)
│  sceneJs.js (插件运行在场景的代码)
│
├─i18n
│      en.js (自定义的中文菜单)
│      zh.js (自定义的英文菜单)
│
└─runtime_Ts
    │  before_sources.meta
    │  now_show_sources.meta
    │
    ├─before_sources (主要备份文件用)
    │      @types.d.ts.zip (Cocos 的一些代码)
    │      auto_bindResTo_nodeTree.zip (主要代码备份)
    │
    └─now_show_sources
        │  autoBind-crypto-js.min.js (AES 加解密资源的文件)
        │  autoBind-crypto-js.min.js.meta
        │  autoBind_i18n_zh_en.meta
        │  auto_bindResTo_nodeTree.ts (主要绑定资源文件的所有代码 > 1000 行)
        │  auto_bindResTo_nodeTree.ts.meta
        │  auto_bindRes_json.json (测试的 JSON 文件)
        │  auto_bindRes_json.json.meta
        │  auto_bind_img_.meta
        │  auto_bind_mp3_.meta
        │  auto_bind_prefab_.meta
        │
        ├─autoBind_i18n_zh_en (失败的多语言代码)
        │      autoBind_i18n_zh_enTs.ts
        │      autoBind_i18n_zh_enTs.ts.meta
        │
        ├─auto_bind_img_ (自制的简单类型的图片)
        │      cocos_j_00.jpg
        │      cocos_j_00.jpg.meta
        │      cocos_j_01.jpg
        │      cocos_j_01.jpg.meta
        │      cocos_j_02.jpg
        │      cocos_j_02.jpg.meta
        │      cocos_j_03.jpg
        │      cocos_j_03.jpg.meta
        │      cocos_j_04.jpg
        │      cocos_j_04.jpg.meta
        │      cocos_j_05.jpg
        │      cocos_j_05.jpg.meta
        │      cocos_j_06.jpg
        │      cocos_j_06.jpg.meta
        │      cocos_j_07.jpg
        │      cocos_j_07.jpg.meta
        │      cocos_j_08.jpg
        │      cocos_j_08.jpg.meta
        │      cocos_p_00.png
        │      cocos_p_00.png.meta
        │      cocos_p_01.png
        │      cocos_p_01.png.meta
        │      cocos_p_02.png
        │      cocos_p_02.png.meta
        │      cocos_p_03.png
        │      cocos_p_03.png.meta
        │      cocos_p_04.png
        │      cocos_p_04.png.meta
        │      cocos_p_05.png
        │      cocos_p_05.png.meta
        │      cocos_p_06.png
        │      cocos_p_06.png.meta
        │      cocos_p_07.png
        │      cocos_p_07.png.meta
        │      cocos_p_08.png
        │      cocos_p_08.png.meta
        │
        ├─auto_bind_mp3_ (简单 MP3 文件)
        │      auto_bind_mp3_0.mp3
        │      auto_bind_mp3_0.mp3.meta
        │      auto_bind_mp3_1.mp3
        │      auto_bind_mp3_1.mp3.meta
        │      auto_bind_mp3_2.mp3
        │      auto_bind_mp3_2.mp3.meta
        │      auto_bind_mp3_3.mp3
        │      auto_bind_mp3_3.mp3.meta
        │      auto_bind_mp3_4.mp3
        │      auto_bind_mp3_4.mp3.meta
        │      auto_bind_mp3_5.mp3
        │      auto_bind_mp3_5.mp3.meta
        │      auto_bind_mp3_6.mp3
        │      auto_bind_mp3_6.mp3.meta
        │
        └─auto_bind_prefab_ (简单预制体文件)
                auto_bind_prefab_0.prefab
                auto_bind_prefab_0.prefab.meta
                auto_bind_prefab_1.prefab
                auto_bind_prefab_1.prefab.meta
                auto_bind_prefab_10.prefab
                auto_bind_prefab_10.prefab.meta
                auto_bind_prefab_11.prefab
                auto_bind_prefab_11.prefab.meta
                auto_bind_prefab_12.prefab
                auto_bind_prefab_12.prefab.meta
                auto_bind_prefab_13.prefab
                auto_bind_prefab_13.prefab.meta
                auto_bind_prefab_14.prefab
                auto_bind_prefab_14.prefab.meta
                auto_bind_prefab_15.prefab
                auto_bind_prefab_15.prefab.meta
                auto_bind_prefab_16.prefab
                auto_bind_prefab_16.prefab.meta
                auto_bind_prefab_17.prefab
                auto_bind_prefab_17.prefab.meta
                auto_bind_prefab_18.prefab
                auto_bind_prefab_18.prefab.meta
                auto_bind_prefab_2.prefab
                auto_bind_prefab_2.prefab.meta
                auto_bind_prefab_3.prefab
                auto_bind_prefab_3.prefab.meta
                auto_bind_prefab_4.prefab
                auto_bind_prefab_4.prefab.meta
                auto_bind_prefab_5.prefab
                auto_bind_prefab_5.prefab.meta
                auto_bind_prefab_6.prefab
                auto_bind_prefab_6.prefab.meta
                auto_bind_prefab_7.prefab
                auto_bind_prefab_7.prefab.meta
                auto_bind_prefab_8.prefab
                auto_bind_prefab_8.prefab.meta
                auto_bind_prefab_9.prefab
                auto_bind_prefab_9.prefab.meta

引用参考

  • 快捷键以及其它请参考 官方文档
  • Cocos 论坛和 Cocos 公众号里面的 AES 加密的 crypto-js 代码

后续计划 (免费更新)

  • 优化使用体验
  • 或增或减内容

补充说明

  • 目前的是Beta版本, 功能不多, 请酌情考虑是否购买
  • 后续功能完善后,价格也会随之提高,感谢支持
  • 如果有发现bug,请联系我,我会尽快修复
  • 感谢各位的支持

购买须知

  • 请各位朋友看后仔细思考,是否符合您的项目或者研究需求,谨慎使用
  • 目前内容相对比较少, 后续才会迭代
  • 因为本产品为付费虚拟商品,一经购买成功概不退款,请在购买谨慎确认购买内容。
1赞

大家如果想学习这里面的内容(绑定资源), 可以参考我下方写的代码,

感谢各位的支持 :smile: :smile:

1. 简单代码的运行效果如下 (比较简陋)

2. 简单示例代码:

import { _decorator, Component, Node, Prefab, Mesh } from 'cc';
import { EDITOR } from 'cc/env';
const { ccclass, property, executeInEditMode, disallowMultiple } = _decorator;

@ccclass('bindSomeResTs')
@executeInEditMode(true)
@disallowMultiple(true)
export class bindSomeResTs extends Component {
    _bindOneFile_: boolean = false;
    loopReadIndex: number = 0;
    default_meshes: any = [
        "1263d74c-8167-4928-91a6-4e2672411f47@801ec",
        "1263d74c-8167-4928-91a6-4e2672411f47@2e76e",
        "1263d74c-8167-4928-91a6-4e2672411f47@38fd2",
        "1263d74c-8167-4928-91a6-4e2672411f47@40ece",
        "1263d74c-8167-4928-91a6-4e2672411f47@17020",
        "1263d74c-8167-4928-91a6-4e2672411f47@fc873",
        "1263d74c-8167-4928-91a6-4e2672411f47@8abdc",
        "1263d74c-8167-4928-91a6-4e2672411f47@a804a"
    ];

    @property
    bindFileUUID: string = "1263d74c-8167-4928-91a6-4e2672411f47@8abdc";
    @property(Mesh)
    oneMesh: Mesh = null;

    @property({ displayName: "[绑定]", tooltip: "启动此项, 自动绑定一个 Mesh 文件" })
    set bindOneFile(val) {
        this._bindOneFile_ = val;
        this.loopReadIndex++;
        // this.bindFileUUID = this.default_meshes[Math.floor(Math.random() * this.default_meshes.length)];
        if (this.loopReadIndex > this.default_meshes.length - 1) {
            this.loopReadIndex = 0;
            // console.log('[绑定] ', this.loopReadIndex, this.default_meshes[this.loopReadIndex]);
            this.bindFileUUID = this.default_meshes[0];
        } else {
            this.bindFileUUID = this.default_meshes[this.loopReadIndex];
        };
        if (val) {
            this._bindOneFile_ = false;
            this.bindFileToNode();
        } else {
            this.bindFileToNode();
        };
    };
    get bindOneFile() {
        return this._bindOneFile_;
    };

    async bindFileToNode(bindNodeName: string = "oneMesh", bindType: string = 'cc.Mesh', bindUUID: string = this.bindFileUUID) {
        if (EDITOR) {
            Editor.Message.send('scene', 'set-property',
                {
                    uuid: this.node.uuid,
                    path: `__comps__.0.${bindNodeName}`,
                    dump: {
                        type: bindType,
                        value: {
                            uuid: bindUUID
                        }
                    }
                });
            console.log('[已绑定] ', bindNodeName, bindUUID, bindType);
        };
    };

    // start() {
    // }
    // update(deltaTime: number) {
    // }
};

目前已更新内容

6.4 增强日志信息+添加代码耗时+高亮选中


膜拜大佬 :heartbeat:

1赞

:laughing:
欢迎大佬

请问一下为什么要支持 json?为什么还会有加密?

1赞

感谢 jare 老大的关注,
这个绑定资源的里面, 加入 JSON 文件, 是为了导出绑定关系,
后续直接用这个里面的就行, 比如说如果定义一个 Excel 的表格,
然后里面写了的关卡, 资源, 数据之类的, 再把表格导出成 JSON 格式, 那就直接可以用在资源绑定里面了,
做个记录吧, 至于加密, 这个是为了一些特殊需求用到的, 如果要把 JSON 数据加密的话, 可以用上,

当然如果不需要导出或者使用 JSON 文件也是可以直接绑定的, 算是集成了一些功能,

如果针对一些简单的需求的话, 从那个代码里面拆出来改也是比较简单的, 目前功能模块都分出来处理的.

具体的链接地址不记得了, 之前是在网上有看到一个文章,
是讲的作者遇到的一个问题, 就是说有个表格导出的 关卡 prefab.json 的数据,
然后预制体的命名是比较规范的, JSON 文件里面的内容也比较整齐, 但是手动拖拽又很麻烦,
所以用代码去实现就比较方便, 我这个也是受到那个文章的启发, 然后加了些的功能.

其实单纯绑定资源的话, 没有那个 JSON 关卡之类的要求的话, 那是用不上 JSON 文件.
但是目前来说, 对于关卡编辑 JSON 文件还是用的比较多.

综上来说, JSON 文件就相当于一个定位和记录的作用, 用于绑定需要指定绑定的内容.

@jare 老大 , 我找到原文了, 上次看了忘记收藏了 :rofl:

【声明】 本此引用文章已获得原作者 @2721791961 KuoKuo 授权

非常感谢 @2721791961 大佬的分享和对本次引用的授权 :smile: :smile:

【原文标题】拖挺好!下次不许再拖了

拖挺好!下次不许再拖了! | KUOKUO的个人网站

【原文作者】KuoKuo CocosCreator

摘要

CocosCreator的组件面板拖拽式对于游戏开发来说很方便,但是有时候面对数量过多的资源,拖拽就成了一件痛苦的事情!

正文

使用工具

  • CocosCreator 版本 3.4.0

故事从一张 Excel 讲起

小明刚来到游戏项目组,一切对于他来说都是陌生的,但是上一位同事走的匆忙,活也没干完,老板没给他时间熟悉。

这不,对接策划来了!策划给小明描述了他的宏大设想,然后解释了文档上的各个要点,最后甩给了他一个活与一张表,要将 CocosCreator 项目完善:

小明一看,哈哈,这活我熟,拖就完了!

这时小明一位菜菜同事路过,还给小明支了一招,你猜是啥?

原来是让拖拽时能近一些,妙啊~

偷懒! 使用消息系统代替拖入

第二天,小明带着黑眼圈来上班,步履蹒跚。阔阔看到了觉得很奇怪,便上前关心询问,原来是策划又做好了 500 个物品描述信息,让小明加上。好家伙,听小明说他硬生生拖了一整夜,我直接好家伙!

本着同事之间要互帮互助、团结友爱,我就帮小明搞了一下自动化。

先安装一下 npm i node-xlsx 库,这是一个解析 Excel 表格的库,然后将数据以 json 的形式抽离出来。

有了 json 数据,我们就还需要解决一个问题,如何找到 CocosCreator 内的资源?不同版本的 CocosCreator 会有不同的 IPC 通信 API,查询对应版本的文档,发现在 3.4 版本中可以使用 Editor.Message.requestEditor.Message.send 来进行消息通信。

官方文档链接:

https://docs.cocos.com/creator/manual/zh/editor/extension/messages.html

在 CocosCreator 中,菜单栏中 开发者 -> Export .d.ts 来导出 Ts 声明文件, 开发者 -> 消息列表 和 消息调试工具 来帮助我们查看内部消息的通讯,拖入预制体资源会触发 set-property 这个核心消息(详见下图):

发现核心消息 set-property 的参数是利用点进行参数拼接,数字代表的意思清晰明了。根据以上信息就可以配合 executeInEditMode 使得脚本在编辑器环境运行然后设置好属性(给出代码):

import { _decorator, Component, Node, Prefab, CCInteger } from 'cc'
import { EDITOR } from 'cc/env'
const { ccclass, property, executeInEditMode } = _decorator

/** 一个物品信息包括一个预制体,数量 和 描述信息 */
@ccclass('ItemInfo')
class ItemInfo {
    @property(Prefab)
    prefab: Prefab = null

    @property(CCInteger)
    count: number = 0

    @property
    desc: string = ''
}

@ccclass('Root')
// 确保在编辑器内能运行,onLoad 会直接执行
@executeInEditMode(true)
export class Root extends Component {

    @property(ItemInfo)
    itemInfos: ItemInfo[] = []

    async onLoad() {
        // 这里可以拖入导出的 json 文件获得,我直接 copy 过来示意一下
        const data = [
            [ 'item-00', 3, '描述0号' ],
            [ 'item-01', 15, '描述1号' ],
            [ 'item-02', 27, '描述2号' ],
            [ 'item-03', 39, '描述3号' ],
            [ 'item-04', 5, '描述4号' ],
            [ 'item-05', 63, '描述5号' ],
            [ 'item-06', 75, '描述6号' ],
            [ 'item-07', 28, '描述7号' ],
            [ 'item-08', 99, '描述8号' ],
            [ 'item-09', 11, '描述9号' ],
            [ 'item-10', 64, '描述10号' ],
            [ 'item-11', 69, '描述11号' ],
            [ 'item-12', 5, '描述12号' ],
            [ 'item-13', 63, '描述13号' ],
            [ 'item-14', 75, '描述14号' ],
            [ 'item-15', 27, '描述15号' ],
            [ 'item-16', 1, '描述16号' ],
            [ 'item-17', 45, '描述17号' ],
            [ 'item-18', 7, '描述18号' ],
            [ 'item-19', 21, '描述19号' ]
        ]
        // 只在编辑器环境运行
        if (EDITOR) {
            // 查询 uuid
            for (let i = 0; i < data.length; ++i) {
                const queryPath = `db://assets//prefabs//item-${i < 10 ? '0' + i : i}.prefab`
                const prefabUuid = await Editor.Message.request('asset-db', 'query-uuid', queryPath)
                // 根据查询的信息进行预制体装入
                Editor.Message.send('scene', 'set-property',
                {
                    uuid: this.node.uuid,
                    path: `__comps__.0.itemInfos.${i}.prefab`,
                    dump: {
                        type: 'cc.Prefab',
                        value: {
                            uuid: prefabUuid
                        }
                    }
                })
                // 普通属性直接赋值即可
                this.itemInfos[i].count = data[i][1] as number
                this.itemInfos[i].desc = data[i][2] as string
            }
        }
    }

    start() {
    }
}

写好代码,测试一下:

插件化

核心逻辑其实就那两个 API,插件化也不过是创建一个插件面板。在插件中可以引入 node-xlsx ,然后做个按钮调用打开 Excel 表,将转化 json 数据过程集成进来,关于插件面板,可以按照官方文档来搞一下,然后引入 Editor.Message.requestEditor.Message.send('scene', 'set-property', ... 即可!

https://docs.cocos.com/creator/manual/zh/editor/extension/readme.html

好了,小明同学终于可以不用拖一整夜了,帮他做好自动化后,临走,我跟他说:虽然拖挺好,但是下次不许再拖了!

更多文章与分享

个人网站:www.kuokuo666.com

2022!Day Day Up!

补充内容

[插件报错] Cocos Creator 3.5.2 版本 addComponent: Failed to get class [记录+解决] - Creator 3.x - Cocos中文社区

有点困惑.
这种情况一般会让程序动态加载资源吧,不会手动拖这么多吧

1赞

是的很少,不过如果类似需要绑定多个音乐资源的话,这种形式会稍微简单一些

了解了,感谢!

1赞