一旦代码写错了,就会每秒60个左右地在不停报错,导致浏览器卡死,引擎那边报错不能优化下吗

但是我还有个问题,重启 VM 条件是什么?一直抛Error?那么如果这个 error 不会影响到游戏卡死,闪屏这些呢,以及基本都会接入的 bugly,bugly 也会使用这些接口吧,那么你的修改还会生效吗

其实这是我编辑器里弄scrollview时,出了错误,等我发现报错了,再回去看下怎么修改,然后再切回浏览器,浏览器就快卡死了。先不管用户,就是影响开发效率,当然自己手动onerror监听错误然后停止引擎渲染也能避免,就是觉得不太好 :joy:

要啥bugly,看他们的意思,上线的东西就不可能有bug,只能怪自己技术水平太低了

目前是__errorHandler收到错误就会重启,我这错误大概率是意料之外的,意料之外也就没办法确定对游戏影响多大了,所以直接重启,好在出现的概率不高
debug包会在ts里处理__errorHandler,信息上传给loki做记录
release会交给java处理

恰恰相反,就因为Bug多才在乎Bug处理方式 :joy:

你这方式,你的用户没有意见吗?出现bug,不管影不影响后续,就直接重启

我这边的用户,哪怕出现bug后,数据不对了,大部分用户都只会反馈给我们,但是你敢卡死或者闪退,秒申请退款 :joy:

我只能说这样搞项目用户流失 double,引擎的 bug 还是有不少

奥,我发现了,好像是我没说明白
我们这对于上线项目肯定是避免卡死或闪退。
我是说开发阶段 是不是也需要处理 这个包还没到用户手里,是否直接暴露问题更好

问题是,一直循环报错,也不好处理bug啊,所以我并不反对报错,也不会要求所谓的报错还能正常什么的,但至少的,不要一直给我循环报

对对对,报错我是想引擎报一两个就行了,别一直不停地报 :joy:,错误我已经看到了,就别让我浏览器卡死 :joy:

js的报错就是这样。。。
都是引擎估计为之,就是引擎故意的,不跳过改帧,一定要暴露给开发者,但包出去了,就是测试员工和上线用户看见的就是卡死,想给你反馈都无法。
因为你的bug,用户流失了,这锅谁背好?

从cocos-lua转过来的用户完全不能理解,当初lua版本报错后,后面的程序还能继续跑。

引擎组不改,那只有自己改。
1,在任何可能出问题的地方(一般是实例对象)添加是否存在,是否正在被销毁的判断。
2,修改js引擎,在tween这些位置添加trycatch
3,平台添加后台上报,同样报错内容只上报一次(只对上线项目,非常重要,因为用户出了问题,只能跟踪日志)

引擎修改见:JS报错无限循环,出不去怎么破,客户端卡死

报错监听见:

catchJsError(){
    function uploadErrorLog(errorInfo,needBase64:boolean = true){
        let key:string = Base64.encode(errorInfo);
        key = StringUtil.randomString(8);
        errorInfo += "mid = " + playerManager.getMySelf().getUId();
        let ver = SqlUtil.get(Const.HOT_UPDATE_VERSION) ? SqlUtil.get(Const.HOT_UPDATE_VERSION) : Const.HOT_UPDATE_MIN_VERSION;
        let version = "v" + Const.GAME_VERSION_UPDATE + "." + ver;
        errorInfo += version;
        // console.log("====uploadErrorLog:",key,errorInfo)
        bridge.umengError(key, errorInfo);
    }

    window["uploadLog"] = function(file_prefix:string = ""){
        if (!Util.isWeb()){
            let url = "http://192.168.0.100/mm/uploadlog.php";
            let all_log = Logger.getLastAllLog();
            let log_name = file_prefix+Logger.getFileName(playerManager.getMySelf().getUId());
            
            console.log("===ready up load file:",log_name);
            let params = {
                filename:log_name,
                key:"file",
                data:all_log
            }
            if (CC_DEBUG){
                NetHttp.uploadFile2(url,params,()=>{
                    engine.gui.toast("client log file upload success!!");
                });
            }
        }
    }
    if(Util.isWeb()){
        let __handler;

        if(window.onerror){
            __handler = window.onerror;
        }
        
        window.onerror = function(...args){
            let errorInfo:string = "";
            Logger.erroring("游戏报错,WEB系统");
            if(args){
                if(args[0]){
                    errorInfo += args[0] + "\n";
                }
                
                if(args[1]){
                    errorInfo += "Location:" + args[1] + "\n";
                }

                if(args[2]){
                    errorInfo += "Line: Row =" + args[2] + "; Col = " + args[3] + "\n";
                }
            }
            Logger.erroring(errorInfo)
            uploadErrorLog(errorInfo);

            if(__handler){
                __handler(...args);
            }
        }

    }else{
        let __handler;
        if (window["__errorHandler"]) {
            __handler = window["__errorHandler"]
        }
        window["__errorHandler"] = function (...args) {
            Logger.erroring("游戏报错,原生系统");
            let errorInfo:string = "";
            if(args){
                if(args[0]){
                    errorInfo += args[0] + "\n";
                }
                
                if(args[1]){
                    errorInfo += "Location:" + args[1] + "\n";
                }

                if(args[2]){
                    errorInfo += "Line: Row =" + args[2] + "; Col = " + args[3] + "\n";
                }
            }
            Logger.erroring(errorInfo)
            uploadErrorLog(errorInfo);
            // 如果是debug模式,上传日志到内网方便查看
            
            // handleError(...args);
            if (__handler) {
                __handler(...args)
            }
        }
    }

    window["tryCatchError"] = function(args){
        engine.gui.toast("游戏报错,tryCatch,错误日志自动上报");
        console.log(args);
        Logger.erroring("游戏报错,tryCatch");
        Logger.trace(args.stack);
        // uploadErrorLog(args);
        if (CC_DEBUG){
            window["uploadLog"]("JS_ERROR");
        }
    }

这个可以试试将引擎的渲染代码中的循环调用脚本遍历的时候捕获错误,这样就可以不会影响渲染了,但也会又错误的提示出来

普通项目或者调试可以,线上不能这么干,trycatch比较影响性能

chrome devtool 有一个 :pause_button: pause on exceptions 选项. 异常自动暂停, 都省的你去找了.

1赞

关注一下.

不能因为一个错误就停止整个项目的渲染,单次运行出错,表示此次运行的指令队列就会终结。你这个明显是在update里面重复调用才会一直报错的,截图里面都有运行的堆栈信息。如果不是在update里面调用,在游戏主循环、其他的循环或者无限循环、递归里面调用都会出现这种情况,正常一次指令运行只会报一个错,然后终止此次指令。只有重复尝试指令队列才会一直报错。

引擎不会因为特定情况给你优化,而是一套完整的运行机制。也恰恰就是这种特性,才能让你更快定位到报错代码是在何处发生的。

以前上线后有一个组件 start 失败,就会导致后面所有组件没调用 start 导致报错。这个问题后来引擎也修复了啊。引擎在开发时会想方设法暴露问题,但是上线后的错误都是能避免尽量避免的。

这里会循环报错的原因我前面解释了,这里是渲染有问题导致报错,渲染底层的错误无法判断错误来源。

结贴了,兄弟们来这两个帖子 :face_with_monocle: