美文网首页CocosCreator
cocoscreator项目优化全解

cocoscreator项目优化全解

作者: 亮亮同学 | 来源:发表于2021-08-05 16:01 被阅读0次

    技术 117871561 交流
    cocoscreator2.4.x版本

    内存管理

    官方参考文档:https://docs.cocos.com/creator/manual/zh/asset-manager/release-manager.html?q=

    cocos2.4版本后 引擎通过cc.assetManager管理所有的 资源,在资源加载完成后,会被临时缓存到 cc.assetManager 中,以便下次复用。但是这也会造成内存和显存的持续增长,所以有些资源如果不需要用到,可以通过 自动释放 或者 手动释放 的方式进行释放。释放资源将会销毁资源的所有内部属性,比如渲染层的相关数据,并移出缓存,从而释放内存和显存(对纹理而言)。

    内存管理机制:

    cocoscreator的内存管理机制 其实就是 对 cc.asset的实例 的引用计数的管理 ,通过对cc.asset实例(资源如texture,spriteframe)的引用计数的增减 来判断是否 释放 资源。

    释放检查

    为了避免错误释放正在使用的资源造成渲染或其他问题,Creator 会在自动释放资源之前进行一系列的检查,只有检查通过了,才会进行自动释放。

    1. 如果资源的引用计数为 0,即没有其他地方引用到该资源,则无需做后续检查,直接摧毁该资源,移除缓存。

    2. 资源一旦被移除,会同步触发其依赖资源的释放检查,将移除缓存后的资源的 直接 依赖资源(不包含后代)的引用都减 1,并同步触发释放检查。

    3. 如果资源的引用计数不为 0,即存在其他地方引用到该资源,此时需要进行循环引用检查,避免出现自己的后代引用自己的情况。如果循环引用检查完成之后引用计数仍不为 0,则终止释放,否则直接摧毁该资源,移除缓存,并触发其依赖资源的释放检查(同步骤 2)。

    实际操作

    有 cc.Asset 实例都拥有成员函数 cc.Asset.addRef 和 cc.Asset.decRef,分别用于增加和减少引用计数。一旦引用计数为零,Creator 会对资源进行自动释放(需要先通过释放检查,具体可参考下部分内容的介绍)

    start () {
        cc.resources.load('images/background', cc.Texture2D, (err, texture) => {
            this.texture = texture;
            // 当需要使用资源时,增加其引用
            texture.addRef();
            // ...
        });
    }
    
    onDestroy () {
        // 当不需要使用资源时,减少引用
        // Creator 会在调用 decRef 后尝试对其进行自动释放,释放前会进行上面所说的释放检查步骤
        this.texture.decRef();
    }
    
    为什么会有 资源的静态引用管理和 资源的动态引用管理?

    Asset Manager 提供了一套基于引用计数的资源释放机制,让开发者可以简单高效地释放资源,不用担心项目规模的急剧膨胀。需要说明的是 Asset Manager 只会自动统计资源之间的静态引用,并不能真实地反应资源在游戏中被动态引用的情况,动态引用还需要开发者进行控制以保证资源能够被正确释放。原因如下:

    1,JavaScript 是拥有垃圾回收机制的语言,会对其内存进行管理,在浏览器环境中引擎无法知道某个资源是否被销毁。
    2,JavaScript 无法提供赋值运算符的重载,而引用计数的统计则高度依赖于赋值运算符的重载。

    cocoscreator中管理内存的两种方式:资源的静态引用管理,资源的动态引用管理

    1,静态引用管理: 当开发者在编辑器中编辑资源时(例如场景、预制体、材质等),需要在这些资源的属性中配置一些其他的资源,例如在材质中设置贴图,在场景的 Sprite 组件上设置 SpriteFrame。那么这些引用关系会被记录在资源的序列化数据中,引擎可以通过这些数据分析出依赖资源列表,像这样的引用关系就是静态引用。

    2,动态引用管理:当开发者在编辑器中没有对资源做任何设置,而是通过代码动态加载资源并设置到场景的组件上,则资源的引用关系不会记录在序列化数据中,引擎无法统计到这部分的引用关系,这些引用关系就是动态引用。

    内存优化

    按钮 或者 纯色背景 用九宫格减少纹理加载后的内存占用

    动画尽量用龙骨或者spine 尽量少用 帧动画

    压缩纹理,参考我的另一篇文章https://www.jianshu.com/p/4c5cbdf98cafcup不会缓存纹理

    资源加载引用的管理,按照项目需要及时释放资源 与保留常驻资源。

    渲染优化

    1,drawcall优化 自动图集或者碎图打成大图 ,归类,公共/特殊场景。设置合理的层级,增加cocos的合批渲染,减少因为cpu的状态切换导致的性能损耗参考我这篇文章《cocoscreator 2.4.x版本 drawcall优化 第一期(掌握控制drawcall数量的必要知识)》(公众号里有 )

    ,2, 压缩纹理,参考我的另一篇文章《cocosCreator 压缩纹理及详细介绍 (性能优化必看,改)》 减少 cup的 解码压力

    3, 设置 合适的帧率,战斗场景 和其他场景
    4, label尽量 尽量不用系统字 用bmfont 字 (但是会有内存消耗的缺点),label会打断核批,也可以选用label的缓存模式:
    1)bitmap:将文本作为静态图像,加入动态图集进行合批,缺点是内容不能频繁更新。
    2)char:将 文本拆分成字符,并缓存到一张字符图集中复用,适用于重复,频繁更新的内容

    个人建议:选择bnfont位图字。稳定除非对内存要求很高

    5, 减少节点树深度和节点数量
    6,合理降低纹理像素深度即 rgb/rgba像素格式(例如某些界面的纹理贴图 采用rgba8888 有的界面贴图用rgba4444格式)

    注意:第6条仅作参考 ,因为目前cocoscreator项目中纹理加载到内存中 像素格式都会转为rgba8888格式。所以 按照理论上来说 降低纹理像素深度 不会对内存产生影响。

    加载优化

    1, 分帧加载,减少大量节点在同一帧创建带来的卡顿
    2, 采用节点池机制 避免频繁销毁创建 带来的性能 损耗
    3 静默加载 :比如在 大厅场景,预加载游戏场景的资源

    4,添加loading界面 ,在loading的时候加载资源,加载完毕 进入场景
    5, 自动图集或者碎图打成大图 ,减少io 。
    6, 拆分 预制体 将大的预制体 拆分成 多个小的预制体
    7,scrollview 优化 滑动过程中动态设置元素,实现元素资源重复使用(多见于背包和排行榜系统,百度一下有很多例子)
    8),根据不同的功能,需求 ,设置 多个assetbundle,将资源,场景,逻辑放在里面,需要时进行加载
    参考我的这篇文章《我理解的 cocosCreator asset Bundle 版本2.4.4》 (公众号里有)

    包体优化:

    一 .贴图资源:

    1)按钮和纯色背景图用九宫格
    设置:在编辑器中,找到要设置的图片,可以在纯色图片的右侧属性栏中找到 编辑 然后根据比例设置九宫格图片的拉伸区域。
    解析:一般九宫格图片尺寸比较小,当一个纯色的按钮或者背景图等等 需要 大尺寸的图片时 ,这时候用九宫格图片 就会比原尺寸图小很多,达到缩小包体的效果。

    2)合理使用jpg代替png图片用作背景图片
    解析:同尺寸的 jpg图片文件要比png图片文件 小一些,因为 jpg和png都是一种图片压缩格式,jpg为有损压缩 png为无损压缩,所以 png要比jpg质量要高,同时 占用的存储也就越多 。通常情况下项目中还是以png格式为主(jpg 在加载到内存时会有一个加载峰值大概是 2-3倍左右 png也会有但是 只有1倍左右。稳定后 所占用的内存一样)

    3)合理复用可复用的资源
    解析:在游戏项目中 占用 项目体积最多的就是纹理,所以更多的复用图片资源 就意味着 达到相同效果情况下 项目的包体 就越小。

    4)用龙骨和spine动画代替帧动画,减少过多资源带来的包体影响

    解析:
    帧动画:在游戏进行的每一帧,记录当先渲染图片/精灵的位置,在目标位置实时渲染出该精灵。每一帧刷新渲染区域,完成一个动画需要比较多的图片。
    骨骼动画:随着图像渲染从CPU->GPU,渲染的内容从记录每个精灵改为记录需要渲染的位置。设计骨头的顶点,骨头之间的联系。设计蒙皮(图片精灵),蒙皮的坐标,展示的顶点。骨骼动画通过算法计算渲染的位置来实现的

    比较:实现一组相同的动画 骨骼动画 需要的资源比帧动画少很多,在项目中 使用骨骼动画 可以减少包体和运行时的内存压力,相反,骨骼动画会浪费更多的时间用于计算。也就是说 两者是 空间与时间 互换的衡量过程。

    通常情况下,小的公司,有可能因为成本原因招不到会骨骼动画得美术,所以还是会考虑用帧动画。这些需要根据 最终项目呈现出来的 体验 来判断是否需要进行优化。

    5)合理降低纹理像素深度即 rgb/rgba像素格式(例如某些界面的纹理贴图 采用rgba8888 有的界面贴图用rgba4444格式)

    解析:纹理的像素格式决定了该纹理能表示的最多像素种类和数量,例如rgba8888每个颜色分量 占用8位 那么这种像素格式的 纹理 每像素占用8 * 4 = 32位 即4个字节。如果用rgba4444像素格式,每个颜色分量占用4位 那么每个像素占用4 * 4 = 16位 即2个字节。也就是说 两张同样大小的纹理前者要比后者多占用一般的存储单位。

    6)压缩图片资源(pngyu或其他压缩软件)

    7)如果打包成app可以尝试选择压缩纹理。
    解析:压缩纹理后的文件要比 png jpg文件大好几倍,但是 打包时 进行压缩后,包体相较要小很多。

    二.音效资源:

    1)降低音效采样率,声道 (背景音乐占比最大)

    三.字体资源:

    1)如果用的ttf字体 ,可以用fontmin裁剪 字库
    解析:字库一般有几兆大小 ,可以通过 fontmin 输入项目中用到的字,从字库中提取就好了。

    2)尽可能使用系统字不会额外增加包体大小,可以用 系统字的缓存模式 中对应的模式来优化dc带来的困扰

    3)位图字(bitmapfont),把不需要的字剔除掉(弊端,内存占用大);
    解析:位图字其实就是纹理,加载到内存中 会占用比较大的内存。优点是 速度快。

    四.引擎方面:

    1)裁剪引擎,把用不到的模块 取消勾选。

    五.远程加载:

    1)设置远程加载文件夹为asset bundle 放在远程,用到时再去加载使用

    碰撞优化

    四叉树结合cocoscreator碰撞逻辑(百度搜索就可以找到相关的解释)

    代码级别优化

    1,运行速度上以空间换时间 为中心(比如Map代替数组)

    2, 排序算法 用快速排序等牺牲空间 减少时间的算法 代替 选择排序 或 冒泡排序

    ,3,尽量用es6新特性,功能分模块,避免 代码冗余,代码简洁易懂 注释用/***/ 避免注释滞后。

    ,4,数组的重置 用arr.length = 0 而不用arr = [] 因为 arr = [] 只是 将arr赋值给另一个引用 这个引用指向的是堆内另一块内存 ,原来arr的引用指向的内存 依然 不会被释放掉

    相关文章

      网友评论

        本文标题:cocoscreator项目优化全解

        本文链接:https://www.haomeiwen.com/subject/ebsjmltx.html