细数微信小游戏中的一些坑,请各位对号入座

了解我的朋友估计知道,之前我自己写了个2D canvas库ycc-engine。库的功能模块基本都有了,有介绍,有示例,有demo,有API文档,唯独还缺一个上线的产品来为库做支撑,缺乏说服力。于是突发奇想,索性做一个微信小游戏来试试库的各种功能是否完善,性能是否可以接受。

直到今日,小游戏的开发也基本完成了,我这一路趟着河踩着坑过来的,不把这些坑指出来,心里实在是不痛快!于是就有了今天这篇吐槽微信小游戏的文章。

注意了:如下任何一点都是作者我本人亲身经历的,问题的解决都是花精力和时间各种试验出来的,希望能帮到同样在开发微信小游戏的你。

坑一:wx.getUserInfo接口更改,必须使用官方的createUserInfoButton创建按钮,而且必须让用户点一下

这个问题可以说是微信小游戏里影响范围最广,用户反映最强烈的了。

对于微信内的小游戏来说,获取当前登录人的微信个人信息,是最最最基本的了。但是呢,微信作死升级,直接把之前的老接口getUserInfo给弃用了,必须采用新的策略来获取用户信息,这就导致了之前很大一批微信小游戏开发者获取不到用户信息,连游戏都进不去。

可以戳这个链接查看官方发布的帖子:https://developers.weixin.qq.com/community/develop/doc/0000a26e1aca6012e896a517556c01

帖子下99%的留言全是怼腾讯产品的,这里就上一个点赞最多的图片,感受一下开发者那种无可奈何的愤怒吧~

640.gif

在微信上玩过小游戏或者用过小程序的人可能都知道,之前绝大多数小程序获取用户信息的时机,都是在用户刚进入应用的时候弹出一个授权窗口,界面大致如下:

屏幕快照 2019-10-25 下午6.55.26.png

而现在使用createUserInfoButton绘制按钮的方式不行了,程序不能主动弹出这个窗口,必须由用户点击一次来触发。

至于微信为什么要这么做,可以查看一下官方的另一篇帖子:https://developers.weixin.qq.com/community/develop/doc/000c2424654c40bd9c960e71e5b009

下边留言区也是怨声载道,有的直接开怼,有的帮产品分析逻辑,还有的想法清奇,想直接来份万名书要求改回来,哈,幼稚~

说实话,用户信息这种基础性的接口,微信的升级改版实在是太暴力,对于这种纯粹一刀切的做法不得不说:坑!

坑二:小游戏的开放数据域

开放数据域是做好友排行榜的时候遇到的,官方的意思是用它来保护用户的关系链数据,不能随意的获取,只能在一个独立的封闭的环境下才能获得这些关系数据。目前来看,关于这个封闭环境,我遇到的坑是最多的,上面那个坑好歹有解决办法,这个坑遇到了,估计连解决办法都没有。

开放数据域坑一:开放数据域与主域的编译方式不一样

具体哪儿不一样,我也不知道,因为开发者工具都是自动编译的,没有给你配置的机会!

如果你使用了async/await这个es6之后的特性,并且游戏需要做一个好友排行榜查看玩家在好友中的排名情况,那么恭喜你,你已经入坑了!

如果你主域和开放数据域都使用了async/await,这个时候你或许会遇到如下的错误信息:

regeneratorRuntime is not defined

并且这个错误信息只有在开放数据域才会报出来。

这个时候,或许你会百度一下寻求解决办法,于是就有人就提出解决方案了。要使用async/await,控制面板开启一下增强编译就行啦!

这个配置的位置如下:

1572181505750345.png

行吧,我们就把那个增强编译勾上,再次编译。这个时候主域又会报一大堆错误出来,具体错误信息如下:

Uncaught ReferenceError: loadBabelMod is not defined

只要你主域使用一次import就会报一次这个错误,这个时候你的心里是不是非常的堵得慌呢?

不开增强编译,开放数据域的编译报错!

开启增强编译,主域的编译报错!

这编译环境,这开放数据域,要让程序员脑细胞死一大片啊!

解决:

最后实在没办法,入了微信小游戏这个坑,这么快就放弃也不是我的风格!两个域的编译环境不一样,我就不用你这破环境!我自己搭个编译环境还不行吗?我自己搭个编译环境还不行么?我自己搭个编译环境还不行吗!

微信这编译环境我们仔细想想不还是webpack编译的吗?于是呢,我们就自己搭建一个编译环境,分别编译两个bundle.js。一个给主域,一个给开放数据域,只要让它们这两个域最终运行的代码是es5的代码就OK了!

对于regeneratorRuntime的问题,我们需要引入它的包,并附加至小游戏的全局变量GameGlobal,如下:

// 解决报错regeneratorRuntime is not defined
GameGlobal.regeneratorRuntime = null;
require('./js/libs/regenerator-runtime');

接下来,主域的game.js再加载我们统一编译的bundle.js,大致就如下这样了:

GameGlobal.regeneratorRuntime = null;
require('./js/libs/regenerator-runtime');
// 引入入口文件
require("./dist/main_entry.bundle.js");

开放数据域的index.js也是这样

GameGlobal.regeneratorRuntime = null;
require('./js/libs/regenerator-runtime');
// 引入入口文件
require("./dist/open_data_entry.bundle.js");

用自己搭建的环境就是不一样,远离腾讯,世界清静~

开放数据域坑二:不能使用云函数,不能加载本地图片、音频等资源

对于不能使用云函数,我忍了,毕竟也不是什么大问题。

解决办法就是:在主域中拉取数据库的数据,通过postMessage传递给开放数据域。

这OK,没问题,考虑开放数据域的封闭独立性,这很好理解。

本地资源的加载,官方说是可以,但我在开发时,在模拟器上就请求超时了!

1572183974119598.png

鉴于之前的坑,我就算了吧,资源我们也单独加载吧!

如下是官方文档中给出的解决办法:

1572184052123453.png

看见没,不止数据需要从主域拉取,连这些个资源,也需要先从主域下载,再通知给开放数据域!

真坑啊!

开放数据域坑三:主域能通知开放数据域,而开放数据域却不能通知主域

这啥意思呢?

举个例子:主域用postMessage给开放数据域发送消息(要求它绘制排行榜),开放数据域收到消息,并执行这个消息。

具体开放数据域执行到哪一步,主域是没办法知道的。到底开没开始绘制,绘制是否报错,绘制结束了没,这些基本的状态主域一个不知道!

主域只能像个傻瓜一样,不停的将开放数据域的sharedCanvas绘制到当前canvas,主域不知道自己绘制的sharedCanvas是个什么东西

这个坑,我是不打算填了!关于它的需求统统砍掉吧!!

之前我设计的好友排行榜,是可以在排行榜列表给好友点赞的。这个点赞按钮是个桃心,点击之后如果成功,则桃心需要改变成红色。就这么个简单的需求,我发现竟然实现不了!!!

原因就在于这个点赞过程是在开放数据域中进行的,它里面桃心的点击过程,主域根本不知道!

最后,不得不把这个排行榜列表点赞的需求,砍掉了~

坑三:不能使用eval、new Function来动态执行Js代码

对于这个坑还是很好理解的,毕竟为了安全问题,动态将字符串当成代码来执行确实不妥。

但是,如果你恰好用到某个库使用了这些受限制的函数或者方法,那么再次恭喜你,你又入坑了!

这坑是解决不了的,你能做的就是换一个库。

对于微信小游戏中受限制的函数可不止这两个,还有很多,这里是官方列出来的一个详细清单,自己在写的时候需要特别注意:https://developers.weixin.qq.com/minigame/dev/guide/runtime/js-support.html

另外需要提醒一下,webpack打包时的devtool配置项,有个eval-source-map模式,这种带有eval的模式都是不能使用的,因为它编译后的代码是会带eval关键字的,大家伙要注意一下哦!

最后

自己这小游戏功能也不是很多,遇到最难搞的坑大概也就这些了,另外还有些小问题,比如版本、包大小等就不再一一列举了!

最后,希望自己的这篇文章能被转发,能被分享出去,因为这样就可以解救更多还处在水深火热的坑里的朋友了!

小游戏二维码

必须上个小游戏的二维码,才能证明这些坑我填过啊~

1572355723994593.png

我的联系方式

QQ群:439366057

邮箱:xiaohei@lizhiqianduan.com

公众号:三天不装逼浑身不自在的小黑哥

1572416815129344.png



打赏作者

发表评论

电子邮件地址不会被公开。 必填项已用*标注