cocos creator初学者对于cocos代码优化的记录

943 阅读3分钟

前言

新入职公司,有幸开始互动游戏开发,目前刚刚涉及cocos三个月,记录一下写cocos学到的新东西

一,获取宽高不要使用根节点宽高,可能存在设置了宽高,但是实际为0的情况,使用

//视图中canvas尺寸
console.log("Maya canvas size:", cc.view.getCanvasSize());
//视图中窗口可见区域尺寸
console.log("Maya visible Size:", cc.view.getVisibleSize());
//设计分辨率
console.log("Maya DesignResolutionSize Size:", cc.view.getDesignResolutionSize());
//屏幕尺寸
console.log("Maya frame size", cc.view.getFrameSize());
// 为当前的游戏窗口的大小
console.log('Maya game size', cc.winSize)

二,使用cocos定时器取代代替定时器setTimeout

this.scheduleOnce(() => {
    // 代码逻辑
}, 1);

三,可以利用浏览器的事件循环机制,异步加载prefab

for (let i = num; i > 0; i--) {
    // 异步创建,优化加载速度
    this.scheduleOnce(() => {
        const ins = cc.instantiate(this.redBagPrefab);
    }, 0.1);
}

四,使用cocos中的Math,代替原生Math

// 随机整数
cc.math.randomRangeInt(min, max);
// 随机浮点数
cc.math.randomRange(min, max);

五,尽量少的操作节点,直接操作节点会导致canvas重绘

六,使用缓动系统代替动作系统

animation(node) {
    cc.tween(node)
        .to(0.5, { position: new cc.Vec3(node.x, 0) })
        .start();
},

七,Label字体优化

动态的字体,比如倒计时,积分数量,使用CHAR模式

不是动态的字体,比如标题,使用BITMAP模式

八,如果有多个spine动画的话,尽量减少spine动画的资源加载次数,可以把多个动画效果,放到一个spine里面,然后调用

// 一次性请求
const allSpineUrl = this.assetMgr.getSpine(this.props['all-spine']);
allSpineUrl.then(res => {
  this.allSpine = res;
});

// 使用
this.countdownSpine.skeletonData = this.allSpine;
this.countdownSpine.setAnimation(0, 'daojishi_default', false);

// 使用
this.backgroundSpine.skeletonData = this.allSpine;
this.backgroundSpine.setAnimation(0, 'default', true);

九,多次创建prefab,可以使用节点池

// 定义
properties: { widgetPool: cc.NodePool }

// 使用,实例
this.widgetPool = new cc.NodePool();

// 使用,添加节点
this.scheduleOnce(() => {
  const ins = cc.instantiate(this.redBagPrefab);
  this.widgetPool.put(ins);
}, 0.1);

// 使用,获取节点
let redbag = null;
if (this.widgetPool.size() > 0) {
  redbag = this.widgetPool.get();
} else {
  redbag = cc.instantiate(this.redBagPrefab);
}

// 使用,不用时销毁
this.widgetPool.clear();

十,多次创建prefab可以选择优化策略,优化多次创建性能

十一,资源加载放到onLoad生命周期里,节点操作放到start生命周期里,根据帧率操作放到update生命周期里

十二,使用代码控制节点的zindex改变层级的方式,不如换成另外一种,使用鼠标在编辑器拖拽一下

十三,查找子节点的时候使用 cc.find('start', this.node) 替代 this.node.children

原因,你可能在编辑器拖拽一下,然后你children获取到的节点顺序就变了😭😭😭

十四,始终使用批量绘图,将同一图层中的精灵图像打包成一个大的图集

十五,尽量保持 绘制调用(draw call) 次数低于 50,总之尽量减少就对了

十六,使用骨骼动画的时候,如果你想要快速判断动画的名字是否在骨骼动画中存在的时候,可以使用以下API判断

const name = 'loding';
const nodeSp = node.getComponent(sp.Skeleton);
let hasName = false;
// 判断
if (nodeSp.findAnimation(name)) {
    hasName = true;
}

十七,如果内存多的话,可以开启动态合图,减少draw call

// 开启动态合图
cc.macro.CLEANUP_IMAGE_CACHE = false;
cc.dynamicAtlasManager.enabled = true;

// 还可通过以下api设置动态合图大小
cc.dynamicAtlasManager.maxFrameSize = 512;

十八,如果只是想要单指触摸,可以使用以下API设置

// 关闭多点触摸事件
cc.macro.ENABLE_MULTI_TOUCH = false;

十九,定时器使用的时候,要用时间戳做判断,不要用+=或者-=,使用+=或者-=回导致定时器不准确的情况

this.fillRangeNode.fillRange = 1;
// 获取到组件结束的时间
const endTime = new Date().getTime() + this.durationTime * 1000;
const timer = () => {
    if (this.fillRangeNode.fillRange <= 0) {
        this.fillRangeNode.fillRange = 0;
        ......
        ......
        ......
        // 清除倒计时
        this.unschedule(timer);
    }
    const ct = endTime - new Date().getTime();
    // 组件的进度等于,当前的时间差除以组件持续时间
    this.fillRangeNode.fillRange = ct / (this.durationTime * 1000);
};

this.schedule(timer, 0.1);

二十,如果想要判断是否手机还是ipad的话,可以使用长宽比来做判断

deviceType() {
    const designRotate = 1440 / 924;
    const visibleSize = cc.view.getVisibleSize();
    const visibleRotate = visibleSize.width / visibleSize.height;
    if (visibleRotate > designRotate) {
        return 'mobile';
    } else {
        return 'pad';
    }
},

尾言

目前就这么多,以后有再添加