游戏开发遇到的奇怪问题(一)

  • ~1.99K 字
  1. 1. 💢 天杀的iOS!!!
  2. 2. 问题&复现
  3. 3. 解决方案

cover

💢 天杀的iOS!!!

公司的测试机全都没法复现,只有策划的iOS才能复现的神人bug。

问题&复现

iOS在关闭WiFi的时候Socket不会立马断开(不管打没打开蜂窝网络),所以会导致在断开WiFi的时候,如果玩家的交互会与服务器进行数据传输,客户端的表现为没有反应也就是卡住了。

这个问题要解决的话还好,微信提供了一个监听网络状态的接口wx.onNetworkStatusChange,所以只要监听网络状态,如果网络连接断开了就手动调用下socket.close(),然后正常走重连流程,这样就完美解决这个问题了。

上述操作搞定后在公司的测试机上测了一遍没有问题,但是策划在自己的iOS上测试后发现这个解决方案居然失效了…

然后我就开始加日志,结果发现在手动调用socket.close()之后居然没有触发Socket的onClose事件,奇了怪了…不过我也没多想,手动调用下Socket的onClose回调就行了,这次测试了下没出现问题,就在我以为问题已经解决了后,策划又传来悲报:

策划:“又出问题了,重连几次后卡死了,游戏都进不去了”
我:“……”

没办法,我又拿起他的手机开始测试,发现确实前几次能正常重连上,但是反复几次后就连不上了,而且回到登录页都没法登录了直接。测了好几次后终于也是发现了规律,重连到第五次后就连不上了,服务器也没收到任何协议或请求,加上登录的那一次就是一共5次Socket连接,我就开始在想,微信不会限制了Socket的并发连接数量吧,我一搜还真是。

1.7.0 及以上版本,最多可以同时存在 5 个 WebSocket 连接。

那也不对啊…我不是都有手动调用关闭Socket吗,这个时候突然想起来,哦…所以之前手动调用的socket.close()没有触发onClose事件,然后我就开始猜测前面几次的Socket是不是没有正确关闭,结果一打日志发现,success回调居然还是执行了的,还有这种事!?我当时就奇了怪了…

1
2
3
4
5
6
7
8
9
10
11
12
public close(): void {
this.socketTask?.close({
success: () => {
console.log(`Socket close 成功`);
},
fail: () => {
console.log(`Socket close 失败`);
},
reason: "close"
});
this.socketTask = null;
}

实在没办法了,我开始在网上搜索解决方案,“不可能就我一个遇到这种问题的吧”,一搜,确实能搜出来好些相关的,以为有救了,结果一点进去,全是:

内容不存在

tm的这个微信开放社区也是个sb!受不了了,后来又是问LLM又是找各个论坛,花了一整天的时间,居然没一个方案是有效的…

解决方案

-没有解决方案-

最后是给Socket连接加了个超时定时器,一般来说Socket连接成功或者失败都会执行回调,但是这个bug在Socket第五次连接的时候回调永远不会执行,所以设定了一个5秒的定时器,如果Socket的回调没有被执行就弹窗(直接重启的话玩家还以为闪退了呢)让玩家重启小游戏。

1
2
3
4
5
6
7
8
9
10
11
12
13
this._timer = setTimeout(() => {
this._timer = null;
window["wx"].showModal({
title: "异常",
content: "网络连接出现异常,立即重新启动",
showCancel: false,
success: function(res: any) {
if (res.confirm) {
window["wx"].restartMiniProgram();
}
}
});
}, 5000);
后记

第二天和后端研究了一天,依然没有解决方案,一致认为是微信底层的问题,并且反馈给了微信。

第三天摇了个大佬来看了一个上午,同样认为是微信的问题,说我们代码没问题。