重大BUG!!: [PreviewInEditor] Rect width exceeds maximum margin

  • Creator 版本: 3.8.4

  • 目标平台: 编辑器预览模式

  • 重现方式:

  1. 任意节点,添加Animation组件
  2. 创建多个.anim动画剪辑文件,每个.anim动画剪辑文件添加100张左右的任意尺寸图片,直接挂载到Animation组件上,或者用resource.loadDir()动态加载。
  3. 运行编辑器预览,100%会报错:Rect width exceeds maximum margin: 像下面这样,报一片,数量不一定,好像与某个.anim动画剪辑文件也没必然关系。
    [PreviewInEditor] Rect width exceeds maximum margin: 118/ 229 2
    [PreviewInEditor] Rect width exceeds maximum margin: 100/ 253 2
    [PreviewInEditor] Rect width exceeds maximum margin: 101/ 253 2
    [PreviewInEditor] Rect width exceeds maximum margin: 103/ 123 2
    [PreviewInEditor] Rect width exceeds maximum margin: 102/ 123 2
    [PreviewInEditor] Rect width exceeds maximum margin: 104/ 133 2
    [PreviewInEditor] Rect width exceeds maximum margin: 105/ 133 2
    [PreviewInEditor] Rect width exceeds maximum margin: 106/ 137 2
    [PreviewInEditor] Rect width exceeds maximum margin: 107/ 137 2
    [PreviewInEditor] Rect width exceeds maximum margin: 101/ 151 2
    [PreviewInEditor] Rect width exceeds maximum margin: 100/ 151 2
    [PreviewInEditor] Rect width exceeds maximum margin: 103/ 147 2
    [PreviewInEditor] Rect width exceeds maximum margin: 104/ 449 2
    [PreviewInEditor] Rect width exceeds maximum margin: 102/ 147 2
    [PreviewInEditor] Rect width exceeds maximum margin: 105/ 449 2
    [PreviewInEditor] Rect width exceeds maximum margin: 106/ 595 2
    [PreviewInEditor] Rect width exceeds maximum margin: 111/ 301 2

注:
1.我测试 用的相同精灵帧图片,实际上每个角色动画精灵帧图片应该是不一样的,只是为了模拟复现错误。
2. 错误出现具体需要多少个.anim不一定,我有时候十几个 有时候二十几个,有时候三十几个,具体原因和规律我也不清楚,如果你没出现问题,那肯定是.anim文件不够多。
3. 和图片的尺寸好像也没关系,并且我用TexturePackerGUI生成了图集,然后做.anim,同样会出这种问题。
4. 用resources.loadDir();等方法,我全试过了,通通报错。
5. 我们暂时没用spine 或者 DragonBone动画,或许spine和DragonBone能解决此类问题,但是时间成本,各方面其他成本会增加很多。

重现概率:100% 通过网盘分享的文件:NewProject.7z 链接: https://pan.baidu.com/s/10kmNg22TKWNjC_EyJLwLTA 提取码: 8888

我大概知道了,应该是编辑器预览有问题

好的,我们看看

感谢反馈,看了一下报了: net::ERR_INSUFFICIENT_RESOURCES 这个是下载并发过大导致的,我们已经反馈相关人员了,不过不会进到 387,可以暂时用浏览器预览

或者你在项目里面新建一个空脚本,然后里面加

// @ts-ignore
cc.assetManager.downloader.limited = true;
cc.assetManager.downloader.maxConcurrency = 1500;
cc.assetManager.downloader.maxRequestsPerFrame = 1500;

这里的 1500 可以根据你电脑来调整

辛苦了 好像现在没问题了,但是我们发现个新问题,就是由于动画组件的update是独立运行的,所以假如一个节点的Animation组件挂在了一个循环的clips, 然后这个节点突然用remove 或者destroy,并不会先执行停止所有的clips状态,然后再移除组件,这样就导致了,循环动画的死循环,最后客户端崩溃。 [PreviewInEditor] Cannot read property ‘_uiProps’ of null
TypeError: Cannot read property ‘_uiProps’ of null
at Sprite._applySpriteSize (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:103867:27)
at Sprite._applySpriteFrame (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:103934:18)
at Sprite.set spriteFrame (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:103529:16)
at Sprite. (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\app.asar\builtin\scene\dist\script\3d\manager\asset\asset-watcher.ccc:1:1091)
at Object.setValue (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:122680:47)
at TrackEvalStatus.evaluate (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:9507:19)
at AnimationClipEvaluation.evaluate (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:9734:49)
at AnimationState._sampleCurves (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:11513:22)
at AnimationState.simpleProcess (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:11556:16)
at AnimationState._process (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:11518:18)
at AnimationState.update (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:11461:16)
at AnimationManager.update (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:10914:20)
at Director.tick (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:17655:34)
at Game._updateCallback (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:19321:22)
at updateCallback (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\resources\3d\engine\bin.cache\dev\editor\bundled\index.js:78612:20)
at sentryWrapped (C:\ProgramData\cocos\editors\Creator\3.8.4\resources\app.asar\node_modules\src\helpers.ts:100:17)

@max 有没有办法给你们内部控制动画循环播放的方法里加一个检测,如果没有组件之类的,就结束循环,或者循环次数达到一定值就结束循环,这样可以避免死循环导致的客户端崩溃。 其实对用户来说 动画播放不出来不要紧(无非可能看不到某个角色,刷新下可能就好了),但是死循环一定会崩溃,直接卡死。 并且目前我不知道到底是隐藏掉Animation组件的节点导致的这个问题,还是移除掉Animation组件的节点导致的这个问题。我在节点被remove之前,先清理了组件的动画状态,但是没用,偶尔还会死循环:/**
* 安全移除动画组件中的所有剪辑并清理残留状态
* @param animationComponent 动画组件
*/
removeAllClips(animationComponent: Animation) {
if (!animationComponent || !animationComponent.isValid) {
return;
}

    try {
        // 1. 先停止所有动画播放,避免移除剪辑时仍在播放
        animationComponent.stop();
        // 2. 禁用动画组件,防止后续更新
        animationComponent.enabled = false;

        // 3. 复制剪辑列表再遍历(避免遍历中修改原数组导致的索引问题)
        const clipsCopy = animationComponent.clips ? [...animationComponent.clips] : [];
        clipsCopy.forEach((clip: AnimationClip) => {
            if (clip && clip.isValid) {
                // 移除剪辑并销毁(暂时不销毁剪辑资源,为了复用)
                animationComponent.removeClip(clip, false);
                
                // 额外清理该剪辑可能残留的状态
                const state = animationComponent.getState(clip.name);
                if (state) {
                    state.destroy();
                }
            }
        });

        // 3. 清空剪辑列表(确保无残留引用)
        animationComponent.clips.length = 0;

    } catch (error) {
        console.error("移除动画剪辑失败:", error);
    }
}

之前代码中我写的 animationComponent.removeClip(clip, true); 强制移除动画状态,但是依然报错

@max @Knox 你好, 用destroy()移除节点,导致循环动画死循环报错问题,有办法解决么?有没有什么安全移除节点的方法?