微信小游戏 - 运行时分析

本文作者:易旭昕

原文链接:https://zhuanlan.zhihu.com/p/33802815

----

这是个人关于微信小游戏系列文章的第二篇(第一篇:微信小游戏 - Canvas/WebGL Demo 移植),在这系列文章里会描述 ——

  • 如何把一些 Canvas/WebGL Demo 移植到小游戏环境并支持双端运行;

  • 对小游戏在 Android 平台的运行时架构进行分析;

  • 通过对移植的 Canvas/WebGL Demo 在小游戏和 Chrome for Android 浏览器上做 Benchmarking,对 H5 游戏 vs 小游戏的渲染性能进行对比和分析;

本文对运行时的分析只针对 Android 平台,并不包括 iOS 平台。另外小游戏实现代码并没有开源,以下分析都是使用 Profile 工具进行外部分析加上部分猜测的结果,不保证完全正确。

窗口结构

小游戏包含了两个全屏的窗口,一个是 Activity 的主窗口,用于绘制 Canvas 之外的其它 UI 元素,比如上图右上角的菜单按钮,右下角的 vConsole 按钮,左上角的 FPS 标签;另外一个是 GLSurfaceView,嵌入到 Activity 的 View Hierachy 里面,用于 Canvas 的绘制。

这是典型的 SurfaceView 的用法,位于主窗口之下,View Hierarchy 的绘制在碰到 SurfaceView 的时候会 Clear 主窗口的相应区域,让位于下方的由 SurfaceView 创建的 Window 可以透出来。这样 View Hierarchy 中位于 SurfaceView 之上的其它 View 看起来就像是悬浮在上面。
type   |       frame         | name 
-----------+---------------------+------
       HWC | 0,    0, 1440, 2560 | SurfaceView - com.tencent.mm/com.tencent.mm.plugin.appbrand.ui.AppBrandUI
       HWC | 0,    0, 1440, 2560 | com.tencent.mm/com.tencent.mm.plugin.appbrand.ui.AppBrandUI

运行 “adb shell dumpsys SurfaceFlinger” 可以看到当前参与合成的窗口:

  1. 一个是 Activity 的主窗口 - “AppBrandUI” ;

  2. 另外一个是作为子窗口的 SurfaceView - “SurfaceView”;

运行线程

小游戏运行的线程架构很简单,基本上可以认为是单线程的架构,一个独立线程负责运行 v8 虚拟机,执行 JavaScript 代码,并调用相应的 GL 指令对 GLSurfaceView 进行绘制。GLSurfaceView 所分配的子窗口自己独自更新,跟 Activity 主窗口的合成由 Android 系统的窗口合成器 SurfaceFlinger 来负责。

如果考虑事件处理,会多涉及一个线程,主线程 —— UI 线程接受到事件后发送到小游戏的运行线程,再转换成相应的数据结构传递给 v8 虚拟机去调用注册的事件处理器。

总的来说,这样的窗口结构和线程架构简单而高效,Android 平台上大部分手游多半也是采用相似的架构。

渲染分析

首先小游戏不会为主 Canvas 分配额外的 Buffer,主 Canvas 是直接绘制在 GLSurfaceView 所分配的窗口上,造成的结果是:

  1. 小游戏环境里面只能有一个可以直接显示的 Canvas;

  2. 无论这个 Canvas 在代码里面设置的大小如何,它实际的渲染分辨率都是 GLSurfaceView 的窗口分辨率,也就是运行设备的屏幕分辨率,如果两者长宽比例不一致,可能会出现画面变形的结果;

所以在小游戏里面主 Canvas 的长宽比例最好跟通过 JavaScript 获取的 window 的长宽比例保存一致,另外小游戏主 Canvas 的默认长宽就是 window 的虚拟像素大小。

这种做法单纯从性能的角度来说有好有坏,后面我们在做性能分析的时候再来细述。

对 WebGL 来说,小游戏的实现应该很简单,每个 WebGL API 调用就是直接调用相应的 GL 指令,并没有使用 CommandBuffer 之类的指令缓存,在单线程架构下使用 CommandBuffer 也毫无意义。

2D Canvas 的实现,因为需要将 2D 绘图指令转换成 GL 指令,中间可能有较多的 CPU 开销,使用指令缓存不但可以通过批量发送 GL 指令给 GPU 来提高效率,而且也可以做绘图指令的合并优化,将多个 2D 绘图指令合并成一个 GL 指令,比如同样的 Bitmap 或者 Shape 连续在多个位置重复进行绘制。不过小游戏的实现看起来很简单,就是连续绘制同一个 Bitmap 或者 Shape 指令就会一直被缓存,直到碰到一个不同的 Bitmap 或者 Shape 就会合并处理之前缓存的 Bitmap 或者 Shape 的绘制指令,调用一次 glDrawArrays。另外,并没有看到有将小位图拼接成一个较大 Texture 的机制,可能是收益不大,处理起来也麻烦。


最后

更多精彩,锁定玄说前端

点个在看支持我吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
微信游戏在Unity中运行崩溃可能有多种原因。以下是一些可能导致崩溃的常见原因: 1. 内存泄漏:长运行游戏可能会积累大量的内存使用,如果没有适当地释放资源或处理内存泄漏,可能会导致崩溃。确保在适当的候释放不再使用的资源,并避免频繁的动态内存分配。 2. 性能问题:游戏可能存在性能瓶颈,例如过高的CPU或GPU使用率、大量的渲染操作等。这些问题可能导致游戏在一段间后崩溃。优化游戏性能,使用合理的渲染技术和算法,以及减少不必要的计算和渲染操作。 3. 不稳定的插件或第三方库:如果你在游戏中使用了插件或第三方库,这些插件可能存在问题,导致游戏崩溃。确保使用最新版本的插件,并查看插件的文档或支持论坛,以了解是否有已知的问题或解决方案。 4. 设备兼容性问题:不同设备上的微信游戏可能会有不同的兼容性问题。某些设备上可能存在特定的硬件或软件限制,导致游戏崩溃。测试你的游戏在不同设备上的表现,并尽可能解决设备特定的问题。 如果你无法确定具体的原因,可以尝试以下方法来诊断和解决问题: - 使用Unity的Profiler工具来分析游戏的性能和内存使用情况,查找潜在的问题。 -游戏中添加日志记录,以便在崩溃查看相关信息。 - 更新Unity版本和相关插件到最新版本,以获得最新的修复和改进。 -微信开发者工具中调试游戏,查看是否有错误或警告信息。 如果问题仍然存在,你可能需要进一步研究和调试,或与Unity或微信游戏的开发者社区寻求帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值