Cocos 社区一直是开发者们提出技术问题、解决 Bug、发表自研小游戏、闲聊灌水等获得一手咨讯的宝地。感谢奎特尔星球公众号负责人 Shawn 上线整理了水友们近期最为关注的几大问题,希望有同样疑问的小伙伴都能在此得到解答。
既然有这么流畅的 Cocos 界面
为什么使用它来做 H5 界面?
问:既然有这么流畅的 Cocos 界面,为什么使用 RN 来做界面,这是为什么呢?我觉得所有的 Web 界面都应该用 Cocos 来替换啊。
答:使用游戏引擎 APP 也是可以的,我想到几个原因
1. 游戏引擎制作 UI 成本较高,HTML+CSS+JS 开发 UI 效率和成本最优的;
2. 游戏引擎的界面渲染机制不同(opengl),它比系统原生的渲染消耗更多电池电量;
3. 游戏界面其实是在普通 App 应用上的一个 opening 窗口,为了跨平台使用了 c++、js 等语言,要调用原生设备的能力还需要在不同语言中桥接,既要会游戏引擎,又要会原生开发,人力成本也高。
Cocos Creator 怎么引入外部库?
问:怎么引入外部库,我引用了一个 socket 的库,在新手入门提到的 socket 已经过期了,无法下载,现在我能在浏览器里面预览,但无法打包发布?另外还有怎么改端口和服务器连接测试?
方案1:将三方库放入 assets,在需要使用的地方使用 requre 引入;
方案2:将三方库放入 assets,选中 js 代码文件,在属性编辑器上勾选“导入为插件”,大多三方库导入的模块为全局变量,类似你在 index.html 中导入;
方案3:在工程目录下创建一个 build-templates 目录,对应 build 工程目录结构,构建时将三方库复制到构建工程中,创建自己的 index.html 模板,但是在调试时对三方库的使是会报错的,不推介这种方式;
方案4:可以使用 npm 管理三方库,代码中使用 requre 引入,但官方不推介使用 npm,会有冗余代码在项目中,这个有点不爽。
creator 中
如何给一个预制体中的按钮添加一个点击事件?
问:我制作了一个预制资源,这个预制资源中有一个按钮。当我在 Layout 节点下面生成这个预制体后,如何给他上面的按钮添加一个点击事件,弹出一个提示框?在生成的时候我给他添加了一个标签,所以可以根据这个 标签拿到这个按钮,但是怎么给他添加点击事件?我用了 this.button.node.on(),但是这个好像只能在 onLoad 中使用,在生产预制资源的方法中使用会报 “on” 没有被定义的错。各位大神帮帮忙!
答:可以在实例化 prefab 时,用代码创建事件监听
let node = cc.instantiate(prefab);
this.layout.addChild(node);
node.on(cc.Node.EventType.TOUCH_END, (touchEvent) => {
cc.log('点击事件在此');
})
如何获取 resources 里
某个文件的真实安装路径?
问:在安卓和苹果端需要取 creator 中 resources 文件里的文件用,问下,这怎么获取,有相关的 API?
答:试试下面这个
let url = cc.url.raw('resources/xxx');
cc.log(url);
cocos2d-js 如何使用自带的 require?
问:如题,windows 系统命令行创建的 cocos2d-js 工程,无法使用 cocos2d-html5 自带的 require , 但 js-test 里有用到 require,不解。把 js-test 用到 require 的相关 js 文件添加到 jslist 中也出现 require undefined …
答:cocos2d-js 项目可以使用 webpack 或 browserify 进行代码编译,文件以模块的方式编写,可以使用 require、exports 导入导出模块。 有个demo,可以参考。Github地址:https://github.com/ShawnZhang2015/c2js-puremvc
游戏的源代码放在 js 目录下,使用 browserify 打包后输出到 src 目录。此方法支持 web 和 native。
protobufjs 序列化后如何拼接上消息 ID?
问:protobufjs 序列化后得到的是 arrayBuffer
let pb = pbkiller.loadAll('proto', '');
let player = new pb.UserLoginMsgReq();
player.openID = 0;
player.logintype = 3;
player.gameID = 3;
let data = player.toArrayBuffer();
如何在 data 前面加上消息 ID 以便服务收到数据后进行反序列化?
答:可以参考 Cocos 插件商店的 pbkiller 插件,所有 potobuf 数据都需要事先定义,参考下面做法
//在proto中定义一个前后端通用的协议
message PBMessage {
uint32 id = 0; //消息ID
bytes data = 1; //上层协议(二进制数据)
}
...
//游戏代码中用法:
let data = player.toArrayBuffer();
//实例化一个PBMessage消息
let message = new pb.PBMessage();
//设置消息ID和数据
message.id = xxx;
message.data = data;
//将message序列化发给服务器,服务器需要做两次反序列化
socket.send(message.toArrayBuffer());
此方法需要前后端配合,后端解码 PBMessage,通过 PBMessage.id 将其路由给具体的处理函数解码 PBMessage.data。
在选中构建的时候选中调试模式
怎么去掉左下角的信息?
问:
答:构建时关闭调试模式
再问:我需要的是在需要开启调试模式的情况下;
再答:用下面的方法可以
cc.director.setDisplayStats(false);
Cocos Creator 打开错误!
问:有没有好心人能告诉我一下这个问题是什么。刚下载下来什么都还没做,就冒出个问题出来。新手求大佬告知,关于这个问题我真的头大。
答:spawn 是 nodejs 的执行外部命令的函数(创建子进程),有可能是环境变量问题,运行外部程序失败了。
两个方案:
1、尝试可以正常编译、预览游戏吗?如果可以,只是编辑器启动时报这个错,暂时不理会它;
2、换用 1.6 的版本试试,是否也有这个问题;
3、还有就是打开 creator 的开发者工具:
反馈:非常感谢您对我的帮助,游戏能正常启动,1.6的版本也有这个问题,我现在调试一下看看。
creator 触摸事件关不掉?
问:
答:上面 this.btleft.on 函数第二个参数是个匿名函数,off 时又是一个新的匿名函数,当然关不掉。给你两种方法:
你可以用 targetOff,但会把所有事件给关了;
将事件函数变成成员函数或子函数;
{
//定义一个事件函数
_eventFunc() {
...
}
//注册事件
this.node.on('xxx', this._eventFunc, this);
...
//关闭事件
this.node.off('xxx', this._eventFunc, this);
}
为什么我 Label 的字体大小不能调整?
问:字体 font size 属性有个锁, 是怎么回事?数值也改变不了。
答:Label 处于 SHRINK 模式,Label 的字体大小受 node 的 size 约束,改变 size 大小后就可以调整 FontSize 了。
Node 节点和 sprite 组件
和 sprite 节点关系?
问:Node 节点和 sprite 组件和 new 出来的 sprite 节点是什么关系?
答:给你打个比喻,节点像一个人,组件则像这个人身上的装备,Sprite 就像一件衣服,改变了节点的外观。一个节点可以装备多套装备,装备你还可以自己打造,就是自己写的组件代码。想想常玩的游戏,如魔兽、英雄联盟这些,英雄与装备的设计。
上面的比喻只说单个方向,再给你打个比方: 节点像一台机甲(小时候看过神龙斗士没有?),组件就像坐进机甲里的操纵者,操纵者有自己的特性,让机甲有不同的表现。而且这一台机甲可以坐很多个人,也就是很多个组件。
你说的 new 出来的 sprite,那是 cocos2d-x js 中的概念了,在 creator 中 Sprite 不能直接 new 出来,是先有机甲,再有给机甲中添加一个Sprite。
let node = new cc.Node();
let sprite = node.addComponent(cc.Sprite);
sprite.xxx = yyy; // 给sprite赋值
node.x = 100; //给节点赋值
cc.log(sprite.node === node); // sprite内部操纵node
如果你觉得上面的方式创建一个 Sprite 很麻烦,你将他封装一下,可以尝试下面的方法:
cc.createComponent = function (componentType, parent) {
let node = new cc.Node();
if (parent instanceOf cc.Node) {
node.parent = parent;
}
let component = node.addComponent(componentType);
return component;
};
//创建一个
let sprite = cc.createComponent(cc.Sprite);
let label = cc.createComponent(cc.Label);
推荐你看下节点与组件的概念分享
http://www.jianshu.com/p/fc46301305fa
http://www.jianshu.com/p/2b92157179d3
以上就是近期水友们比较关注并且已经得到合理解决方法的几个典型问题。如果大佬们有其他见解,欢迎文末留言不吝赐教。社区做为集开放性、专业性和功能性为一体的交流服务平台,希望有更多志同道合的水友们参与进来共同探讨和支持。
维护和谐社区,你我有责!
来一下,更有料!