H5游戏性能优化整理(cocos

Stella981
• 阅读 691

近期在一家公司负责H5游戏加载速度优化,这里把近期做的项目优化项做一个整理分享:(若文中有错误的地方,还请指出。)

   分享流程:了解html渲染流程 -> html相关优化 -> http相关优化 -> 项目结构和游戏流程及优化 -> 游戏渲染相关优化 -> 代码编写优化

html渲染流程

HTML解析过程:构建DOM树、构建CSSOM树、根据DOM树和CSSOM树构建render树、有了render树就开始布局Layout、最后绘制paint。

1、构建DOM树:   将HTML构建成一个DOM树,也就是构建节点,把所有的节点都构建出来。

2、构建CSSOM:   解析css去构建CSSOM树。

3、构建render树: DOM已经构建好了,css也有了,浏览器就会根据这两个来构造render树。

4、布局:      当render树有了,通过render树,浏览器开始计算各个节点的位置和样式。

5、绘制:      遍历render树,在页面上绘制每个节点。

6、重排reflow:  当render树绘制完成之后,比如JavaScript改变样式或添加节点,这时候render树就需要重新计算。

7、重绘repaint:  重新绘制页面。

HTML整个解析过程看起来很简单,但是我们要知道解析过程中css、js和dom的加载顺序。我们都知道HTML是自上往下解析的,在解析过程中:

1、如果遇到link和style,那就就会去下载这些外部的css资源,但是css跟DOM的构建是并行的,就是说不会阻塞DOM树的构建。

2、如果遇到script,那么页面就会停止html的解析和渲染把控制权交给JavaScript,直到脚本加载完毕或者是执行完毕。

  1> 没有defer和async标签的script会立即加载并执行。
  2> 有async标签的js,js的加载执行和html的解析和渲染并行。
  3> 有defer标签的js,js的加载和html的解析和渲染并行,但会在html解析完成后执行,在触发DOMContentLoaded事件前执行。

3、页面的渲染是依靠render树,也就是说如果css没有加载完成,页面也不会渲染显示。

4、JavaScript执行过程中有可能需要改变样式,所以css加载也会阻塞JavaScript的加载。

5、JavaScript执行过程中如果操作DOM,但是DOM树又是在JavaScript之后才能构建,就会报错,找不到节点。

6、DOMContentLoaded和onload的区别:DOMContentLoaded在html解析完毕后执行,loload在页面完全加载完成后执行(包括样式和图片)。

html相关优化

其中对我们项目首屏启动速度影响最大的就是网络请求,所以优化的重点就是使用文件缓存和减少Http请求(页面中每发送一次请求,都会完成请求+响应这个完成的HTTP事务,会消耗性能,造成HTTP链接通道阻塞)。

1.html代码压缩。

2.减少页面上引用的文件数量(非首屏依赖CSS或者js文件、图片资源的引用,等首屏展示后静默下载(按实际项目需求))。

3.减少域名查询:DNS查询和解析域名也需要消耗时间,不同域名使用越少越好。

4.优化页面加载顺序:1.将css文件放在head中 2.js放在body的底部。

5.防抖动、节流.

6.css相关优化

  1.正确使用 Display 属性,因为 Display 属性会影响页面的渲染。

  2.避免图片和 iFrame 等空 Src。

  3.尽量避免重设图片大小。

  4.避免 CSS 表达式。

  5.移除空的 CSS 规则。

  6.不滥用 Web 字体、Float。

  7.不声明过多的 Font-Size。

  8.值为 0 时不需要单位。

以下贴出示例的html文件内容,以注释进一步说明优化内容:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>title</title>
    <meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1, minimum-scale=1,maximum-scale=1" />
    <meta name="full-screen" content="yes" />
    <meta name="x5-fullscreen" content="true" />
    <meta name="360-fullscreen" content="true" />
    <meta name="screen-orientation" content="portrait" />
    <meta name="x5-orientation" content="portrait">

    //初始化只加载首屏页面渲染依赖的css文件,非初始化依赖css文件,等游戏主包js下载后初始化由WebCssManager.js动态引入
    <link rel="stylesheet" href="./css/layout.css">

</head>

<body onload="load()">
    <script src="src/res/loading.js"></script> //游戏定制页,在主包下载之前过度显示,避免因下载主包导致首屏展示太慢,提高游戏体验
    <script>
     //SDK或者外部插件,全部由插件管理类管理,初始化依赖的SDK在管理类下载完后立即执行,其他插件或者渠道SDK等主包下载完成后下载
        var loadPluginManager = function() {
            var script = document.createElement('script');
            script.onload = function() {//下载js主包}
            script.onerror = function(err) {loadPluginManager();}
            script.src = "./plugin/webPluginManager.js";
            document.body.appendChild(script);
        }
        loadPluginManager();
    </script>
    <canvas id="gameCanvas" width="1136" height="640"></canvas></body>

</html>//html代码逻辑尽量少,只引入少量文件避免过多的HTTP请求

HTTP相关优化

1.如果支持http合并请求就合并请求。合并资源,减少 HTTP 请求数,minify / gzip 压缩,webP,lazyLoad。
  

 
静态资源打包,因为浏览器下载静态文件的时候是有线程数限制的:同一时间针对同一域名下的请求有一定数量限制,超过限制数目的请求会被阻塞。为了提高性能,服务器端会把js/css  合并成一个文件(因为都是文本嘛)再向客户端输出,这样页面能更快的展现。
2.缓存:HTTP 协议缓存请求,离线缓存 manifest,离线数据缓存localStorage。

项目结构和游戏流程及优化

示例:打包出来的项目结构(不含子包),其中主包js文件大小2.9MB左右,资源文件大概15MB(压缩后,png类型资源在打包的时候会额外生成一份Webp格式(android使用webp、ios使用png))。

项目结构优化:

1.(棋牌大厅)游戏主包或者游戏子包(棋牌游戏)的发布直接覆盖原包内容(便于没变动文件使用缓存),其中主包目录和子包目录独立分开,便于版本缓存管理。

资源相关优化:

1.打包并压缩所有游戏js文件。

2.合并所有CSS文件(按自身项目情况而定)。

3.合并非初始化所需插件或者SDK的js文件(按自身项目情况而定)。

4.压缩图片资源,png纹理生成一份webp格式(并再次压缩75%)供android使用(按自身项目情况而定,因为webp纹理下载后需要解码,算上解码耗时小图使用webp不划算)。

5.合并所有资源集合图plist文件(减少大量http请求数、IO)。

6.项目结构中大厅游戏根据版本号修改html文件和主包文件名,资源文件使用文件MD5命名,游戏子包根据服务器下发版本号区分http请求。

流程逻辑相关优化:

前言:

因为我们游戏APP、微信小程序、h5都是共同游戏服务器,针对h5通讯流程后端没做任何优化,共用一套(连接大厅服务器(含请求进入大厅相关接口)、连接游戏服务器(webSocket)(含请求进入游戏房间相关接口)耗时长),充分利用通讯耗时做该做的事情(如下载图片资源):异步执行游戏中同步顺序执行的逻辑(按实际情况而定)。

   游戏优化前流程(只列举主要流程):

    1.正常方式登录大厅:预览登录资源 -> 连接大厅服务器 -> 请求进入大厅协议 -> 预览大厅主界面资源及通用资源 -> 显示大厅

2.通过分享连接进游戏:预览登录资源 -> 连接大厅服务器 -> 请求进入大厅协议 -> 预览大厅主界面资源及通用资源 -> 显示大厅 -> 连接游戏服务器 -> 请求进入房间 -> 预览游戏资源 -> 显示游戏房间界面

   游戏优化后流程(按实际项目情况而定,主要保持异步耗时平衡):

    1.正常方式登录大厅:

(连接大厅服务器 -> 请求进入大厅协议) 同时异步执行 预览登录和大厅主界面及通用资源 ->  显示大厅

2.通过分享连接进游戏:

(连接大厅服务器 -> 请求进入大厅协议) 同时异步执行 预览登录和通用资源 -> (连接游戏服务器 -> 请求进入房间) 同时异步执行 预览游戏资源 -> 显示游戏房间界面

   详细游戏优化相关说明:

  1.连接大厅服务器、请求大厅相关接口的同时下载游戏资源(部分资源直接载入纹理缓存)(此处必须保持异步平衡,连接大厅耗时充分用来下载和预览资源)(注意控制同时请求数量,因为大部分浏览器并发请求数是4-6个)。

2.进游戏房间同上。

3.异步执行影响游戏流程中部分独立不互相影响的流程(如GPS、影响游戏流程的接口)。

4.通过分享进游戏,只预览少量大厅通用资源和对应游戏资源,跳过大厅相关流程且不创建大厅相关界面,直接进游戏房间(通讯和游戏资源下载预览同上,且保持异步平衡)。

游戏渲染优化

1.相同图集里的图一次性连续渲染完,减少Draw Call。2.减少被遮挡或者超出可视区的单位渲染。3.部分UI元素较多的界面或者场景建议使用分帧加载,元素量大的则规划渲染规则。4.允许情况下减低帧率。

代码编写优化

这里先推荐一本书:《代码整洁之道》:代码质量与其整洁度成正比。干净的代码,既在质量上较为可靠,也为后期维护、升级奠定了良好基础。

js原生库推荐 : Lodash (一个一致性、模块化、高性能的 JavaScript 实用工具库。它内部封装了诸多对字符串、数组、对象等常见数据类型的处理函数)。

1.适当使用函数式编程。

2.尽量使用异步编程。

3.在js中尽量减少闭包的使用。

4.封装尽量做到低耦合高内聚。

5.整理代码规范,避免破窗效应。

6.设计模块化、组件化、分层化。

7.避免使用全局数据。

8.避免编写相似得函数。

9.养成不断的批判对待自己代码的习惯,寻找重新组织、改善结构和正交性机会。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这