2018-09-25

BUG

loading时偶尔卡住bug

表现:无法继续,无报错,出现概率:2/10,所有平台都会重现,引入声音加载后更容易重现。

  • 调试目标:由于声音容易重现,所以从声音模块入手调试。

  • 重现步骤:发现将cpu速度下降,和加载大量声音,和开启大量加载线程,每次进游戏后几乎必现。必现很重要,不然无法确定修改后的bug是否正确。碰到偶然bug,第一时间是看代码逻辑,没法从逻辑中找到问题,只能创造必现的条件。

  • 步骤:

  1. 如何获取卡住的目标模块堆栈信息?卡住后程序实际还在运行,这时候打算加入断点,但目标模块已经不在运行,加入断点也无效,这时候加入的地方是一个系统Timer,当卡住后,在Timer的callback中打断点,游戏主程序会被断下来。

  2. 在Timer打断点,如何才能获取目标模块的内存信息?这时候可以预先在目标模块加入调试代码,例如window.__xxxModule = RES.instance; 将目标的的局部变量引用存到全局变量里面,这样断点的时候可以在watch窗口输入window.__xxxModule查看目标的内存信息。

  3. 查看window.__xxxModule模块后,发现没有声音模块的引用,无法获得声音模块的对象信息,重新修改引擎代码,将声音模块的引用加入到其父模块中,例如RES.instance.sound = sound; 注意新加的引用最好加入到其父模块,阅读大概的加载流程和父子模块的生命周期是否一致,子模块可以由父模块哪些变量管理。加完子引用后重新执行步骤1。

结论:发现加入引用后bug无法重现啊。经分析是白鹭的资源加载模块,没管理子加载模块的引用,导致浏览器在gc的时候被回收,callback无法回调结果卡住。

修复:声音模块引用有问题,需要确定其他加载模块是否也存在同样问题。经发现,图片加载模块也是有bug的,图片加载模块使用了缓存池,前4组线程一旦成功就会被缓存池引用,但万一刚加载就被gc掉了,也会导致卡住的问题。所以都要给父模块加入子模块的引用才行。

关闭某UI时,偶尔报错

表现:报错堆栈被中断,无法获取有效信息。在某些情况下,Timer或者Promise回调回来的堆栈不完整,无法获取所有堆栈内容。出现概率 2/50。

  • 调试目标: 该UI模块

  • 重现步骤:由于出现概率极低,首要任务是将重现概率提高。

  • 步骤:

  1. 由于问题出现在关闭UI的瞬间,只要提升关闭次数,就能提高重现概率,编写测试代码,
while(1000) {
    UIMgr.open(xxx);
    UIMgr.close(xxx);
}

若以上代码不出错,考虑到偶现的都是定时器或者动画引起的,需加入延迟关闭的测试代码,

while(1000) {
    UIMgr.open(xxx);
    Timer.After(1000, UIMgr.close(xxx));
}

结论:经发现,是有子模块的对象没被释放,对象内的定时器还在运行,回调的对象已经无效。

修复:在onExit中加入对子模块的释放。

某动画移动的位置总是不对

表现:某一时刻出现很多飞金币飞资源动画,但只有飞金币动画位置不对,查看代码逻辑没发现问题。

  • 调试目标:仅仅针对飞金币动画。

  • 重现步骤:将飞金币动画和部分模块,迁到登录界面,运行时看是否重现。这里就突显函数封装的重要性,好的程序结构,调试bug也更方便。函数必须是要功能单一和完整的,要做到这样,就要求函数尽量只依赖参数,然后返回结果。少用this对象。尤其是UI动画,按道理来说应该比较独立,对其他UI和业务逻辑依赖比较少才对。

游戏越来越卡

表现:刚进游戏流程,游戏后期很变卡和发热严重。

  • 调试目标:猜测内存泄漏问题

  • 重现步骤:有可能是常用的UI模块或者某重复创建销毁的大对象释放有误导致的。

  • 步骤:

  1. 假设是最消耗内存的骨骼动画释放问题:在游戏登录界面,编写测试代码,增加两个button: add/sub, addBtn创建1000个骨骼动画, subBtn删除1000个骨骼动画,重复操作几次,若是界面骨骼动画数量为0时,内存和cpu都没法下降,必然是骨骼动画释放机制有错,导致内存泄漏。若是UI问题,操作方式也差不多。

UI关闭时骨骼动画释放偶尔报错

表现:偶尔会出现调用到无效骨骼对象的报错堆栈信息

  • 调试目标:白鹭的骨骼动画,创建是需要加入全局时钟 clock.add(arm); 移除时需要从全局时钟中移除 clock.remove(arm);堆栈信息是从remove中的报错,初步怀疑是没有remove已经释放的arm导致的。但看代码没看出问题所在(其实是有问题的)

  • 重现步骤:出现概率比较低,无法必现。但通过重复开关UI的方式统计错误信息。

  • 步骤:

  1. 给每一个arm对象增加唯一标志: this.name = Math.random();clock.add(arm)的前一句代码中加入 console.log("add:" + this.name); close.remove(arm)前一句代码中加入 console.log("remove:" + this.name); 通过输出log,观察每个对象创建是否都已经被释放。用眼睛看log比较累,其实可以通过写测试模块,封装好关键信息,定时收集,不匹配就输出断言,这样就不需要用眼睛对比log信息。

  2. 经发现,前两次的UI创建和释放log交错输出,统计发现总是差一次释放。

结论:是由于关键的add,remove代码不同步导致的,主要原因是创建骨骼动画是异步回调的。例如:

UIxxx {
    onEnter() {
        let cb = (arm)=> {
            clock.add(arm)
            this.arm = arm;
        }
        createArm(cb)
    }

    onExit() {
        if (this.arm) {
            clock.remove(this.arm);
            this.arm = null
        }
    }
}

修复:关键的add,remove尽量不要引入其他条件判断(谨慎)。进出的逻辑操作一定要尽量贴近对象的创建和释放代码。

某IOS版本上,拖放对象时出现黑块

表现:只在特定IOS版本上才能重现

  • 调试目标:采用debug模块,手机直接输入debug地址

  • 重现步骤:只要拖动就会显示黑块,必现。

  • 步骤:

  1. 初步怀疑是UI中的某些节点干扰,采用排除法,先将无关的节点隐藏。发现还是能重现。

  2. UI没找到问题,接着采用代码屏蔽法,先将拖动的代码注释掉,发现表现正确了。初步确定问题所在。

  3. 逐步注释代码,最后将hitTest(true);修改为hitTest();发现表现正确,而且操作逻辑无误。

结论:使用了特定ios版本不支持的像素检查属性,预估是白鹭的bug.

修复:修改为hitTest()就行了,正常逻辑本来就不需要采用像素检查。

IPHONE SE 二维码无法生成

表现:只在特定iphone se上才能重现

  • 调试目标:采用debug模块,手机直接输入debug地址

  • 重现步骤:必现。要生成二维码的游戏步骤过多,直接将生成代码贴到登录界面,省去loading时间。

  • 步骤:

  1. 查看系统Image加载dataURL的代码,经发现是加载dataURL时WebImage发生错误,但没有输出具体错误信息。

  2. WebImage代码不多,只有十几行,采用代码注释排除法。最后将Image.crossOrigin注释掉。发现二维码能生成了。

结论:iphone_se不支持匿名跨域创建Image DataURL。

修复:在Image loader里面,判断当前src是否dataURL,若是临时关闭跨域属性。

IPHONE X 游戏模糊

表现:经发现,不仅仅是IPHONE X,只要在特定的宽高比就会变得模糊

  • 调试目标:采用浏览器

  • 重现步骤:webgl模式下拖放浏览器,整个游戏会模糊,必现。但canvas没问题。

  • 步骤:

  1. 怀疑白鹭改出bug了

  2. 下载白鹭github上面的工程。

  3. 采用git log -S 命令刷选 模糊 关键字。查看修改的代码,尝试还原测试。

结论:发现有一次代码提交,是修正字体模糊,针对canvas所加的。

if (egret.Capabilities.renderMode == "canvas") {
    canvasScaleX = Math.ceil(canvasScaleX);
    canvasScaleY = Math.ceil(canvasScaleY);
}

修复:发现将针对canvas的条件后注释,模糊问题基本解决;

总结

  1. 创建测试环境
  2. 创建必现条件
  3. 编写测试代码
  4. 注释代码(参考二分查找算法)
  5. 查找历史记录log
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,022评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,710评论 2 59
  • 依稀记得认识你,已经将近两年的时间了。每天出门,你总是早早的摆好了摊子,不论冬夏。有时我会好奇地问“大爷,这么早,...
    米可的花园阅读 470评论 2 5
  • 鉴峰自我管理 [连续签到第40天] 2018-2-17 周六 鉴峰笔记之创造: The best way to p...
    鉴峰笔记阅读 87评论 0 0
  • 再7天,就足足满35周岁了,便可不必冠上各种“35周岁以内XXX”的头衔。悲喜参半,喜的是,不需要被迫硬着头...
    小雨夹雪阅读 371评论 0 0