cocos creator 3.x 开发问题记录

973 阅读4分钟

解决打开webView页面全屏下整体偏移问题

在cocos creator 3.6.1中,webView 页面全屏的效果如下:

1681540488576.png

可以发现全部下的webView页面并没有完成遮挡住背后的内容,而且全部的内容展示不全。 分析主要原因,打开控制台,可以看到

1681540755935.png 在H5端上,cocos creator 对于使用webView的做法是在canvas外 新建一个 id为“webview-wrapper”的标签去嵌套 iframe 去展示对应页面内容,在 “webview-wrapper” 中 引擎会根据设备的像素比例去缩放webview的网页大小

引擎根据设备去缩放内容很关键,迫不得已才会去改引擎,最优的做法引擎缩放完后我们再缩放回来,这样的做法导致的结果就是用户打开的时候会闪一下,但是效果总归是好的。

解决

那引擎什么时候会缩放完,我们不知道,那这种情况下,在webView页面中,我们通关postmessage来做通信。 在webView页面加载完毕后 我们发送通知

window.top.postMessage("onLoadWebView", '*');

在游戏代码中我们去做接收


 window.addEventListener('message', (event) =>{
     if (event.data == "onLoadWebView" && webViewNode) {
            console.log('收到 onLoadWebView');
            var webview = document.getElementById('webview') as HTMLIFrameElement;
            if (webview.src.includes('Advertise')) {
                (window as any).gameTime.stop()
            }
            setTimeout(()=>{
                console.log('设置了');
                document.documentElement.style.overflow='hidden';
                let webviewWrapper = document.getElementById('webview-wrapper') as HTMLElement;
                webviewWrapper.style.top = 0+'px';
                webviewWrapper.style.left = 0+'px';
                webviewWrapper.style.right = 0+'px';
                webviewWrapper.style.bottom = 0+'px';
                webviewWrapper.style.overflow = 'hideen';
                webviewWrapper.style.transform = 'none'
                webviewWrapper.style.width =  '100%'
                webviewWrapper.style.height = window.innerHeight + 'px';
                webviewWrapper.style.height = window.innerHeight + 'px';
            },100)
        }
 }, false);

重设缩放为正常,这样就解决了。

参考: forum.cocos.org/t/webview/9…

解决webView页面输入框弹起键盘页面错乱

当弹起键盘的时候,整个页面空间会因为键盘缩小,cocos creator 默认就是当 页面缩放的时候去重新计算大小,我们只需要在需要的设置

view.resizeWithBrowserSize(false); //注意!该方法在切换场景后要重新设置!不然不生效!

就可以了,禁止页面大小变化时计算宽高大小。

解决一次渲染500 - 700+ 节点 导致的内存泄露引起的卡顿问题

首先游戏类型是类似羊了羊的玩法,在移动端机型上,发现用户越玩手机越烫,越玩越卡的问题,在低端机型还会卡死的问题。 后面在浏览器中对内存进行检测发现,主要原因是因为一次又一次的重新挑战没有正确使用释放内存导致的问题,因为在游戏中,一局游戏中的块在短时间内生成 500 - 700 + 的方块,这样的原因是为了给玩家增加难度,每次重新挑战 即使每次destroy节点了,但是内存并没有少。 解决的第一个方案是使用对象池,对象池的实现原理很简单,虽然在3.x的cocos 文档中,去除了有关NodePool的内容,但是还是可以使用NodePool 去 做对象池的封装,使用对象池,游戏重新挑战后,我们就不需要每次都 创建和销毁了。

下面是对象池封装的代码:

import { NodePool, Prefab, instantiate } from "cc";

    

class Pool {
    static instance: any;
    static prefab: any;
    static enemyPool: any;
    private constructor() {
        Pool.enemyPool = new NodePool();
    }
    public static getPool(prefab){
        let enemy = null;
        if (Pool.enemyPool.size() > 0) { // 通过 size 接口判断对象池中是否有空闲的对象
            console.log("不需要重新创建方块 ====== !!!!!!!!!!");
            
            enemy = Pool.enemyPool.get();
        } else { // 如果没有空闲对象,也就是对象池中备用对象不够时,我们就用 cc.instantiate 重新创建
            Pool.enemyPool.put(instantiate(prefab));
            enemy = Pool.enemyPool.get();
        }
        return enemy;; // 将生成的敌人加入节点树
        // enemy.getComponent('Enemy').init(); //接下来就可以调用 enemy 身上的脚本进行初始化
    }
     public static clearPool(){
        Pool.enemyPool.clear()
    }
     public static putPool(enemy){
        console.log(Pool.enemyPool,'回收后的长度====');
        
        Pool.enemyPool.put(enemy);
    }
    public static init(){
        console.log('初始化内存池');
        this.instance = this.instance || new Pool();
        return this.instance;
    }
    // }
};
export const init = () => Pool.init();//初始化对象池
export const getPool = Pool.getPool; //获取对象
export const clearPool = Pool.clearPool; // 清除对象池
export const putPool = Pool.putPool; //放回对象

由于游戏玩法的特殊性,我们并不知道每一个关卡的具体方块数量(后端返回),而且也不能多创建对象,那如此,初始化内存池后,通关 getPool 去生成和创建对象,当没有对象的时候主动创建然后返回,否则反之,这样重新挑战后就达到复用的结果,在退出当前场景再清空对象池。

使用缓动动画后事件失效

Z轴不能设为0