前言
新入职公司,有幸开始互动游戏开发,目前刚刚涉及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';
}
},
尾言
目前就这么多,以后有再添加