Cocos Creator Tips

在使用Cocos Creator进行游戏开发中,所遇到的一些问题答案和一些小技巧,记录下来。

代码修改后,Chrome调试显示没有改变#

使用CocosCreator开发面临一个问题,代码保存后需要切换回CocosCreator或者在界面上点击Recompile按钮进行编译,不然调试不会编译最新的脚本。

函数作为函数参数#

1
2
3
4
5
6
7
8
load(url, callbackFunction) {
....
callbackFunction(result);
}

load("prefabs/prefab", (result)=>{
consolo.log(result);
});

给弹框的背景加上 置灰层#

在弹框节点中,添加一个覆盖了整个canvas的背景节点,并添加Sprite脚本来完成置灰的颜色效果。通常置灰层都是无法点击的,所以可以在这个置灰节点上,添加一个BlockInputEvents脚本来限制事件。

如何判断undefined和null#

通常选择取反来判断其是否为null或者undefined.

1
2
3
4
5
6
7
8
9
10
let test;
let nulltest = null;

if (!test) {
......
}

if (!nulltest) {
......
}

JavaScript 使用分帧创建对象#

创建一个计时器,以20毫秒为间隔,执行n次(需要创建n个对象),每次只执行一次创建一个对象的方法。

1
2
3
4
5
6
7
8
9
10
let tiemr = setInterval(() => {

if (index < counts) {
this.createItem();
index++;
}
else {
clearInterval(tiemr);
}
}, 20);

可以优化代码阅读和书写的 JavaScript ES6 语法标准#

箭头函数#

1
2
3
node.schedule(()=>{}{
.....
}, 5);

使用let#

1
let x = 10;

推荐 const > let > var .

数组 和 对象 的解构#

1
2
let list = [1, 2, 3];
let [a, b, c] = list;
1
2
3
4
5
6
var obj = {
name: "Tom",
age: 20
};

let {name, age} = obj;

使用 import 代替 require#

旧的写法:

1
2
3
4
5
6
7
8
9
10
11
// data.js
var data = {
name: 'sea',
test: function() {
console.log('test');
}
}
module.exports = data;

// main.js
var data = require('data');

新的写法:

1
2
3
4
5
6
7
8
9
10
let data = {
name: 'sea',
test: function() {
console.log('test');
}
}
export default = data;

// main.js
import data from"./data";

优势在于,更加契合其他语法编码人员的开发习惯,同时 import 带有代码提示,避免书写错误。

ScrollView组件的知识点#

  1. ScrollViewcontent 添加Layout脚本后,可以很方便的约束content下的item位置。Layout模式下的ResizeMode属性中选NONE就可以在数据很少的时候滑动,如果选择CONTAINER模式只有当content的长度大于scrollview的时候才能滑动(CONTAINER模式下,contentsize会随着item的数量多少而变化)。
  2. scrollviewcontent 上面挂载的Layout 组件的功能最好要用自己的代码在 update 接口函数里面实现,使用自带的 Layout 性能比较差。
  3. 当需要显示item比较多的时候,可以只创建少数item,然后在非显示区域,更改item的位置并刷新新数据,来实现少数item显示成多个item的效果。

使用cc.Button组件制作按钮和实现点击事件。#

通常使用this.node.on方法来监听点击事件,但是这种方法有很多局限性,不能完全模拟Button的事件效果,在事件回调里面无法获得当前点击按钮的屏幕坐标点等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 //创建一个事件处理对象。
var clickEventHandler = new cc.Component.EventHandler();
//这个 node 节点是你的事件处理代码组件所属的节点。
clickEventHandler.target = this.node;
//这个是代码文件名。
clickEventHandler.component = "MyComponent";
//事件处理的函数。
clickEventHandler.handler = "callback";
//需要传递的事件参数
clickEventHandler.customEventData = "foobar";

var button = node.getComponent(cc.Button);
button.clickEvents.push(clickEventHandler);


callback: function (event, customEventData) {
//这里 event 是一个 Touch Event 对象,你可以通过 event.target 取到事件的发送节点
var node = event.target;
var button = node.getComponent(cc.Button);
//这里的 customEventData 参数就等于你之前设置的 "foobar"
}

处理 cc.Label 组件设置String后下一帧才刷新大小#

由于 cc.Label_updateRenderData 处理开销过大,导致没办法设置 string 到时候去触发更新,只能在渲染到时候才可以获取到正确的 size,可以在设置 label 所有属性后在执行一次label._updateRenderData(true); 就能带当帧获取大小。

摄像机跟随缓动核心代码#

1
2
mainCamera.x = cc.misc.lerp(mainCamera.x, posX, rate); 
mainCamera.y = cc.misc.lerp(mainCamera.y, posY, rate);

rate 是一个系数,可以设置为0-1之间,posX, posY是计算出来的角色位置,mainCamera是摄像机。

屏幕最佳分辨率#

750x1334

iPhone X 适配#

分辨率适配:过高按宽适配, 过宽按高适配。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cc.Class({
extends: cc.Component,

onLoad() {
let screenSize = cc.View.getFrameSize();
let canvas = this.node.getComponent(cc.Canvas);
canvas.fitWidth = false;
canvas.fitHeight = false;
if (screenSize.height / screenSize.width >= 1.77) {
canvas.fitWidth = true;
} else {
canvas.fitHeight = true;
}
},
});

假随机数#

产生 [ min, max ] 假随机数

let randNumber = Math.floor(Math.random() * (max + 1 - min) + min);

Cocos中的单例#

1
2
3
4
5
6
7
8
9
10
11
12
let Singleton = cc.Class({
statics: {
_instance: null,
getInstance() {
if (!this._instance) {
this._instance = new Singleton();
}
return this._instance;
}
},
});
module.exports = Singleton;

节点的active设置为false后部分代码逻辑无法生效#

在脚本中将 nodeactive 被设置为false 之后,后面的代码逻辑就无法生效,此时只需要先将 nodeopacity 设置为0,然后等逻辑走完之后将 active 设置为 false 即可。

关于start()#

生命周期接口函数 start() 是在所有脚本的 onLoad() 执行完之后执行,所以将初始化工作放在start()里面就可以取到其他脚本的值。

给预制体添加父亲节点#

给预制体添加父亲节点的时候最好使用 parent.addChild(prefabNode); 而不是 prefabNode.parent = 父节点,这样如果父节点名字拼写错误 浏览器会报错 addChild is not definded

世界坐标系和局部坐标系的转换#

  • convertToNodeSpace
  • convertToWorldSpace

  • convertToNodeSpaceAR

  • convertToWorldSpaceAR

这是两套API,其中没有以AR结尾的API的设计是为了和 cocos2d-x 中行为一致。通常我们使用的是以AR结尾的API。而他们的区别则是锚点

node.convertToWorldSpace(cc.p(0,0))是将node的(0,0)(忽略锚点,也就是node的左下角)这个位置转换为世界坐标,所以得到的位置应该是node的左下角相对于世界坐标系原点的偏移量。

convertToWorldSpaceAR则是节点锚点相对于父节点的锚点的Position,在世界坐标系原点的偏移量。

而我们通常使用的是
node.parent.convertToWorldSpaceAR(node.position);
或者
node.convertToWorldSpaceAR(cc.v2(0,0));

Android 打包问题#

项目设置里面模块设置的network要勾选 第一次打包建议全部勾选上 别去模块

常见的打包失败4种问题:

  1. 路径过长
  2. 去掉了必要模块
  3. sdk或ndk版本太老或者太新
  4. 环境变量问题

关于resources文件夹#

如果一份资源不需要由脚本 直接 动态加载,那么千万不要放在 resources 文件夹里。resources 文件夹下放的资源是会被代码动态加载的资源,而不会再代码中动态加载的资源不要放在 resources 文件夹下。

挂载Animation组件的节点使用NodePool的问题#

回收到节点池时会移除节点注册的action动作,但是对于动画只会暂停而不会消除。
所以你需要自己在播放的时候处理一下每次都从头开始重新播放。

在VSCode中,使用debugger可以在代码中模拟断点#

debugger加入代码之后,Chrome会自动在插入它的地方停止,很像Swift里面打断点。你也可以在一些条件控制中插入该调试语句。

1
2
3
if (isSomeThingRun) {
debugger;
}

获取屏幕尺寸#

cocos creator中可以通过cc.winSize获取屏幕尺寸。

1
2
let size = cc.winSize;
layer.setPosition(size.width/2, size.height/2);

动态加载Sprite#

1
2
3
4
var self = this;
cc.loader.loadRes("test assets/image", cc.SpriteFrame, function (err, spriteFrame) {
self.node.getComponent(cc.Sprite).spriteFrame = spriteFrame;
})

在加载图片的时候,实际上我们需要的是SprieFrame
另外,由于匿名函数的作用域和原始空间不同,这里有必要预先使用ar self = this

如何在iOS原生平台调试#

具备以下条件:

  1. Mac版 CocosCreator
  2. Xcode
  3. Safari
  4. iPhone
  • 首先,用CocosCreator构建iOS项目,构建完成后,找到 ios_project文件夹,点开里面的xcode项目。
  • 然后打开iPhone手机,在设置中找到Safari浏览器,然后点进去选择高级,打开web检察器
  • MacSafari浏览器中,打开偏好设置,在高级中选择在菜单栏中显示“开发”菜单
  • 手机连接Mac,用xcode开始调试运行,等游戏运行成功后,在MacSafari浏览器中,打开菜单栏的开发选项,选择正在调试的真机,然后选择Cocos2d-x JSB选项,就可以打开iOS调试的调试器了。而CocosJavaScript代码都编译放在 projec.js中的。

文件夹和资源的命名#

文件夹#

  • 动画:animation
  • 预制:prefab
  • 场景:scene
  • 脚本:scripts
  • 纹理:textures
  • 声音:sound
  • 配置:config

资源#

分类 + 功能(特征) + 序号 来命名。

img_glod.png 金币图片
button_ok_0.png ok类型的按钮图片

关于节点树做功能模块#

小游戏就全部使用节点显隐,大游戏就常用节点的显隐,不常用的节点销毁。

匿名函数中的this#

this对象是在运行时基于函数执行环境绑定的,最终指向的是那个调用它的对象。
但是匿名函数中的this是全局的this

优先位图文字#

很多时候,使用位图文字比使用cc.Label的效率要好

v1.x CocosCreator prefab加载图像显示不全问题#

在旧版本引擎中,引擎对于加载prefab的优化方式固定为“优化多次创建性能”,在需要批量创建对象的场合中效果拔群。但是有不少人将 prefab 作为多人协作或者分步加载的工具,这些 prefab 基本只会实例化一次,就会导致节点创建速度变慢。新版本默认采用“自动调整”以后,很好的解决了这个问题。

因为走的是“优化多次创建性能”模式,所以渲染就只会渲染一次,只要不清掉之后都是复用。

WebView如何和游戏内部交互#

目前 Android 与 IOS 用的机制是,通过截获 url 的跳转,判断 url 前缀的关键字是否与之相同,如果相同则进行回调。

和官方文档一样,需要配置两个函数:

  1. setJavascriptInterfaceScheme 设置scheme
  2. setOnJSCallback 设置回调函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
cc.Class({
extends: cc.Component,
properties: {
webview: cc.WebView,
},

onLoad () {
let scheme = "scheme";// 这里是与内部页面约定的scheme关键字

// scheme://BACK
function jsCallback (webview, url) {
// webview: 对象webview
// url 可以操作的URL
let str = url.replace(scheme + '://', '');
if (str === "BACK") {
console.log("Back!");
}
}

this.webview.setJavascriptInterfaceScheme(scheme);
this.webview.setOnJSCallback(jsCallback);
}
});

官方文档中 jsCallback 函数参数只有url,如果按照文档来,获得的URL实际上是 WebView对象。【记录时间:2020/4/2,记录版本 1.10.2】

如何在加载 WebView 时避免白屏#

由于在 Cocos 中 WebView 的渲染和游戏并不是在同一层,而且 WebView 的层级永远会在顶层,这就导致了不能在 WebView 上面添加自定义UI来设置 Loading 等。而解决方案也很简单:

Loading 为例:

在创建好 WebView 后,将 WebView 移到 显示区域外,而显示区域内再添加一个 Loading 图,然后再监听 WebView 的网页加载状态,当网页加载好了以后,移除 Loading 图,再设置 WebViewPosition 来让其显示到显示区域下。

用Mask组件裁剪制作圆形头像#

Type: 选择Ellipse,这样可以指定多边形,一般64足够了,这样就裁剪出来圆形头像。

cc.director常用API#

方法 功能说明
getWinSize 获取视图的大小,以点为单位,简单来说就是逻辑大小
getWinSizeInPixels 获取视图大小,以像素为单位(这里的像素指的是资源分辨率。 如果要获取屏幕物理分辨率,需要用 cc.view.getFrameSize())
getScene 获取当前的逻辑场景,场景对象下面是Canvas
setDisplayStats 是否显示左下角FPS信息
getCollisionManager 获取碰撞检测管理对象,返回与该cc.director关联的cc.CollisionManager
getPhysicsManager 获取物理引擎管理对象,返回与该cc.director关联的cc.PhysicsManager
loadScene(scene_name) 加载场景,场景的名字,系统会加载对应的场景
preloadScene(scene_name) 预加载场景,但你使用后仍然需要使用cc.director.loadScene()启动场景

安卓和iOS屏幕常亮#

jsb.Device.setKeepScreenOn(true)

CocosCreator web调试默认不显示FPS#

在需要的的地方写上
cc.director.setDisplayStats(false);

在2.1以后的版本中使用:
cc.debug.setDisplayStats(false);

Visual Studio Code 学习 Swift Tips 翻译和笔记

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×