最近在往个人求职项目里导表,发现cocos creator接入Luban存在下述坑点/难点:
1.官方TypeScript使用示例用到了require('fs'),而cocos在不同平台对nodejs及npm的支持可能会有差别,这增加了平台及机型适配方面的风险;同时,加入npm会增加首包大小
2.如果不使用fs,cocos creator3.8.0的resources.load默认异步,在loader方法中直接resources加载,将loader作为参数输入cfg.Tables的构造函数时,cfg.Tables得到的数据为空,因为此时异步加载还没有完成,loader返回为any时直接返回undefined
3.cocos导入json得到的JsonAsset.json是Record<string,any>格式,Record<string,any>没有实现迭代器,导致cfg.Table创建时报错,因为它在代码中使用了for...of
解决方法:
文件加载问题:使用promise和Promise.All,使用resources.load加载所有文件并存入Map<文件名,数据>,之后统一创建Table
迭代器问题:手动创建新类型实现迭代器,或创建方法返回一个迭代器
代码如下,相信稍加修改就能使用,如果有用,麻烦copy之前点个赞
import { _decorator, Component, JsonAsset, Node, resources } from 'cc';
const { ccclass, property } = _decorator;
import * as cfg from '../../Luban/schema/schema';
@ccclass('ItemManager')
export class ItemManager extends Component{
public static instance:ItemManager=null;
public static tables:cfg.Tables=null;
private static jsonDataMap=new Map<string,MyRecord>();
private static jsonFileNames:string[]=[];
protected onLoad(): void {
ItemManager.instance=this;
this.loadLubanName();
this.loadLubanData();
}
public loadLubanName():void
{
ItemManager.tables=new cfg.Tables(this.getFileName);//获取资源路径
}
private getFileName(fileName:string)
{
ItemManager.jsonFileNames.push(fileName);
return [];
}
private loadLubanData()
{
let promises:Promise<unknown>[]=[];
for(let curFileName of ItemManager.jsonFileNames)
{
var promise=new Promise((resolve, reject) => {
resources.load("lubanJson/"+curFileName,JsonAsset,(err,jsonAsset)=>{
ItemManager.jsonDataMap.set(curFileName,jsonAsset.json);
resolve(jsonAsset);
});
});
promise.then((jsonAsset)=>
{
});
promises.push(promise);
}
Promise.all(promises).then((values)=>
{
ItemManager.tables=new cfg.Tables(this.getFileData);
console.log("weapon数据示例:"+ItemManager.tables.TbWeapon.get(1));
});
}
private getFileData(fileName:string):any
{
return iterateRecord(ItemManager.jsonDataMap.get(fileName));
}
}
type MyRecord = Record<string, any>;
function* iterateRecord(record: MyRecord): Generator<any, void, void> {
for (const key in record) {
if (record.hasOwnProperty(key)) {
yield record[key];
}
}
}