最近两个月, 我们一直在用 CocosCreator 做一个休闲游戏, 在享受 Creator 高效的过程中我们也遇到了这样那样的问题. 有些问题是我们的用法不正确, 有些则是引擎和编辑器的 bug, 好在这些问题基本上都解决了.

今天我和大家分享下我们团队在使用 CocosCreaor 遇到的问题及解决方案.

Web 篇

Failed to load resource: net::ERR_BLOCKED_BY_CLIENT

解决方案:
如果你的浏览器装了广告过滤插件的话, 可能是某个文件拦截了, 在这个页面上停用广告拦截插件就行了.

No ‘Access-Control-Allow-Origin’ header is present on the requested

解决方案:
跨域问题, 如果是在开发阶段遇到的话, 我们可以先尝试绕过这个问题. 常用的方案有两个:

  1. 使用 Chrome 插件
  2. 启动 Chrome 时加入允许跨域的参数

可以参考这篇进行配置, 第一个方案有时候会失效, 还是第二个方案最稳妥.

Can not find deps [xxx] for path : preview-scripts/assets/Script/xxx.js

解决方案:
浏览器提示找不到某个文件, 其实是有两个重名的文件放在不同的目录, 改成不一样的文件名就好了.

Native 篇

调用 Objc 函数失败, 提示找不到函数

解决方案:
Objc 函数如果有任何参数的话, 函数名称最后都要加 :, quick 之前是自动补了这个. Objc 函数不支持 NSObject 类型, 只支持基本类型, 之前 quick 都是通过 NSDictory 进行传参的.

iOS 运行无日志输出

解决方案:
binary 模板生成的 iOS 工程出错后没有堆栈信息, 换成了 link/default 模板就解决了, 推测可能是 binary 模板使用的是 Reaease 版的配置编译出的 .a, 因此没有日志.

Android Studio 调试启动很慢

将下图这里改成 Java 就好了, 只是不能 debug c++ 代码了.

error: undefined reference to ‘bsd_signal’

解决方案:
修改 gradle.properties:

1
PROP_TARGET_SDK_VERSION=10 //21 就会报上面的错误

Web 和 Native API 适配篇

atob 和 btoa

这两个 API 只有 web 上有, Native 上没有, 只能自己实现, 我是使用 cryto.js 实现的:

1
2
3
4
5
6
7
export function base64Encode(str: string): string {
return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(str));
}

export function base64Decode(str: string): string {
return CryptoJS.enc.Base64.parse(str).toString(CryptoJS.enc.Utf8);
}

cc.log

在 Native 上无法输出 Object 类型的变量, 可以利用 Json 自己实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const _log = cc.log;

if (cc.sys.isNative) {
// tslint:disable-next-line:only-arrow-functions
cc.log = function() {
const arg = [];
// tslint:disable-next-line:prefer-for-of
for (let index = 0; index < arguments.length; index++) {
const element = arguments[index];
switch (typeof element) {
case "object":
arg.push(JSON.stringify(element));
break;
default:
arg.push(element);
break;
}
}
_log(arg.join(" "));
};
}

WebSocket/XMLHttpRequest

OPEN/CONNECTING/CLOSING/CLOSED 属性在 Native 无定义, 自己实现:

1
2
3
4
5
6
export enum SocketStatus {
OPEN = 1,
CONNECTING = 2,
CLOSING = 3,
CLOSED = 4,
}

同理, XMLHttpRequest.DONE(4) 也是没有定义的, 得自己定义或者直接写数字.

unschedule

unschedule 在 Native 时会额外判断 __callbackId, 这个id是在调用 schedule 时赋值的, 所以以下做法会出错:

  1. schedule 时传入 this.xxx.bind(this)
  2. unschedule 先于 schedule 执行

schedule 函数没有返回 handle, 因此没有办法判断是否 schedule 过, 所以还是用 update 来做计时器.

JS Exception: null is not a function, file: , lineno: 0

解决方案:

1
cc.director.getScheduler().scheduleUpdate(this, 1, false, this.onTimer);

如果 this 不是继承自 cc.Component 的话就会持续的触发这个错误.

诡异现象篇

工程怎么同步都不是最新的代码, 控制台看到了 会话过期 字样

解决方案:
重启 Creator , 猜测是在 git pull 的同时打开了 creator 的原因

启动后游戏背景是蓝色的

解决方案:
之前从测试用例工程拷贝过来的 cases-settings.js 中设置了清屏颜色,

1
cc.director.setClearColor( cc.hexToColor('#2f69d2') );

Creator 打开项目卡死

解决方案:
把整个 assets 目录清空, 能够打开了. 随后通过 git 还原 assets 目录, 就可以正常打开了. 详细过程可以看我在论坛中发的这篇帖子.

preloadScene 调用后 http 请求收不到 response

解决方案:
c++ 侧断点跟踪后, 确实是收到 Response 了, 但是没有调用到 js 这边, 将 onreadystatechange 事件由匿名函数改为成员函数后解决.

localStorage 无法保存存档

解决方案:

1
cc.sys.localStorage.setItem(“storage", "world");

经过排查, 是某些特殊关键字无法存储成功成功, 设置后本次回话有效, 关闭标签后再打开就没有了, 换一个 key 就好了.

认知篇

  1. Event 不能持有对象, 因为 EventPool, 你持有的对象属性会发生变化.
  2. 在 onLoad 之前 active 置为 false 将导致不会触发 onLoad 事件, 直到下次 avtive 为 true 时才会触发.
  3. 动画时间轴, 并不是不等分, 而是前面是秒数, 后面是帧数, 30 就是 1 秒的一半.