• 关于cocos2d性能优化记录


    第二次用cocos写小游戏,以前更新帧没有那么频繁,没有感觉到明显的卡顿,当我用cocos写赛道游戏的时候,卡得我都不想玩游戏了,在各位大佬得指点下和自己对代码的思考,从 frametiem的10ms优化到1ms左右。

    预制体

    预制体创建删除会影响IO,所以尽可能提前生成写入到 预制体池内

        /**

         * 游戏开始时先创建预制体到池内

         */

        createPipe() {

            let pipeNode: Node = null;

            for (let index = 0; index < 10; index++) {

                pipeNode = instantiate(this.pipePreb);

                this.pipePool.put(pipeNode);

            }

        }

    Lable文本

    Cache Mode

    Cache Mode类型选择会大大影响性能

    类型功能说明
    NONE默认值,Label 中的整段文本将生成一张位图。
    BITMAP选择后,Label 中的整段文本仍将生成一张位图,但是会尽量参与 动态合图。只要满足动态合图的要求,就会和动态合图中的其它 Sprite 或者 Label 合并 Draw Call。由于动态合图会占用更多内存,该模式只能用于文本不常更新的 Label。此模式在节点安排合理的情况下可大幅降低 Draw Call,请酌情选择使用
    CHAR原理类似 BMFont,Label 将以“字”为单位将文本缓存到全局共享的位图中,相同字体样式和字号的每个字符将在全局共享一份缓存。能支持文本的频繁修改,对性能和内存最友好。不过目前该模式还存在如下限制,我们将在后续的版本中进行优化:
    1. 该模式只能用于字体样式和字号(通过记录字体的 fontSize、fontFamily、color、outline 为关键信息,以此进行字符的重复使用,其他有使用特殊自定义文本格式的需要注意)固定,并且不会频繁出现巨量未使用过的字符的 Label。这是为了节约缓存,因为全局共享的位图尺寸为 2048 * 2048,只有场景切换时才会清除,一旦位图被占满后新出现的字符将无法渲染。
    2. Overflow 不支持 SHRINK。
    3. 不能参与动态合图(同样启用 CHAR 模式的多个 Label 在渲染顺序不被打断的情况下仍然能合并 Draw Call)
    4. 目前暂不支持 IsBoldIsItalicIsUnderline 属性。

    合并Lable

    游戏内可能合并的Label就合并,不仅仅是Label,所有的游戏资源,能合并就合并

            // 一个 中文字 等于 四个 \t

            this.ShowTextTitle.getComponent(Label).string = "游戏时间\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t当前速度\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t飞行路程(显示一秒刷新一次)";

            this.ShowTextInfo.getComponent(Label).string =  "00分00秒\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0.00米/秒\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0.00米";

    开启动态合图

    目前在小游戏和原生平台上默认会禁用动态合图,但如果你的项目内存空间仍有富余的话建议开启。

    1. macro.CLEANUP_IMAGE_CACHE = false;
    2. dynamicAtlasManager.enabled = true;

     注意:这些代码请写在项目脚本中的最外层,不要写在 onLoad/start 等类函数中,才能确保在项目加载过程中即时生效。否则如果在部分贴图缓存已经释放的情况下才启用动态图集,可能会导致报错。

    如果不开启动态合图的话,Label的Cache Mode使用BITMAP时是无效的

    拆分计算和渲染

    在游戏逻辑内,分计算和渲染两部分,与渲染无直接相关 或 无关的逻辑,应该要用异步或者 在非帧渲染时执行,从而平均和优化渲染的效率,不会出现渲染的时候突然一卡一卡的情况

    官方文档上说:scheduleOnce计时器,可以指定0~N的时长,让回调函数在下一帧立即执行或者在一定的延时之后执行一次回调函数,之后就停止计时。

        // update 后执行

        lateUpdaet(dt){

                    // 当前帧赛道渲染障碍物时,则延迟一帧渲染游戏显示数据

                    this.scheduleOnce(function() {

                        this.isCreatePipe = false;

                        // 计算游戏数据 和 显示

                        this.updateTextInfo();

                    }, 0);

        }

        /**

         * 更新游戏数据显示

         */

        async updateTextInfo() {

            code...

        }

     Cocos Creator官方推荐使用TypeScript开发,默认是支持使用asyncawait的。

    个人测试总结

    这里是个人经验猜测,不确定所有机型和其他情况都能使用。

    在手机端微信小游戏上测试时,发现点击屏幕时,farmetime会突然降低一半左右,在原本的逻辑不变的情况下,猜测可能是和手机运行性能算法有关。故在游戏刚开始时,可以诱导玩家多次点击屏幕来进行游戏加速。

    微信小游戏第一次开始游戏的时候 明显 比重来后 要卡一些,猜测可能游戏运行有预热 或者 二次运行时有缓存加速。

    相同渲染量 在游戏刚开始的时候 比 游戏运行了一段时间后 要卡一些,所以在游戏刚开始的时候添加游戏开始倒计时来缓冲游戏加载,其次在赛道渲染障碍物的时候,游戏前30s左右都只渲染少量的障碍物,30s后开始逐步增加障碍物,来达到平衡游戏性能的目的。

     

  • 相关阅读:
    Scala (十二) --------- IDEA 快捷键
    ES6如何声明一个类?类如何继承?
    RunwayGen2上线全新控制功能「运动笔刷」
    SpringCloud微服务(九)——Ribbon负载均衡
    Unity添加自定义菜单按钮
    TDengine学习(1):采集量(Metric),标签(label),数据采集点,表,超级表,子表、库
    Linux服务器,使用ssh登录时越来越慢,有时甚至出现超时的现象,解决方案
    Convert转换学习
    CSS 平面转换 渐变
    Excel 常用技巧(三)
  • 原文地址:https://blog.csdn.net/shark_pang/article/details/126465667