Asset Bundle从入门到放弃

公司启动新项目。看到cocos creator 更新到了2.4.2
有个新的资源管理方法Asset Bundle,就想用下。

前后发了一个星期时间看文档, 文档写的不清不楚,
逛论坛。发现好像都对Asset Bundle不怎么感兴趣
自己慢慢摸。发现还真是自己太天真了。

总体来说。这个Asset Bundle还是半成品吧

现在发现有两个个问题。
1,文档里说内置bundle可以更新。自己试了下。无效。哪怕就是clearCache也没用
2. bundle里预设是可以更新,但是脚本无效(可能是脚本更不没有加载),我脚本放在预设同一个bundle,脚本也是挂在预设上。每次预设是更新了。脚本还是无效

想想还是用原来的热更算了。

脚本没热更的原因应该是其他地方有依赖,被打到其他bundle里了,你可以看下bundle文件夹下的index.js是不是空的,所以这个bundle更新了,脚本在其他bundle其实还是旧的

现在这个版本的Asset Bundle最大的作用就是拆分小游戏平台资源加载,而且支持打包单个zip,大大减少请求次数

原生平台我们也在评估bundle替代热更,目前感觉还是可行的

1赞

这个脚本只在这个bundle里,也只有这个bundle里面的预设有挂载,index.js里有东西的
感觉有点象u3d里的(脚本不更新)。如果是这样。就意义不大了。
如果bundle的脚本能热更。那就棋牌做子游戏还是不错的,或者模块分开也是不错,那就可以替代原有热更了

那应该是js不能重新加载,不像lua一样,这个还是比较头疼

Asset Bundle的代码加密问题你们要怎么解决?不可能真的不混淆加密就发布吧…

功能都是经过多次测试证实运行正常的,你那边是遇到了什么问题?出现了什么报错?

原生平台自带加密的,web和小游戏平台加密js没意义,只能混淆

我这边是对微信小游戏子包来说有点不尽人意, 引擎2.4版本发布之后, 主包8M, 子包370多k, 而用2.3等版本是主包和子包接近4M. 子包优先级都试了个遍, 有的情况是报错,有的就是出现上述问题.

没有报错
就是没有更新
main.js是这样修改

let bundleRoot = [“assets/resources”, “assets/main”, “assets/internal”];
var count = 0;
function cb(err) {
if (err) return console.error(err.message, err.stack);
count++;
if (count === bundleRoot.length + 1) {
cc.game.run(option, onStart);
}
}
var initBundle = function (bundleversion) {
cc.assetManager.loadScript(settings.jsList.map(function (x) { return ‘src/’ + x; }), cb);
for (let i = 0; i < bundleRoot.length; i++) {
var op = null;
var bundleName = bundleRoot[i];
if (bundleversion && bundleversion[bundleName]) op = { version: bundleversion[bundleName] };
cc.assetManager.loadBundle(bundleRoot[i], op, cb);
}
}
var xhr = new XMLHttpRequest();
xhr.timeout = 5000;
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
var httpDatas = JSON.parse(xhr.responseText);
initBundle(httpDatas);
}
else if (xhr.readyState == 4 && xhr.status == 0) {
initBundle(null);
}
};
var url = ‘http://192.168.68.165:10220/ver.json’;
xhr.open(‘GET’, url, true);
xhr.setRequestHeader(‘Content-Type’, ‘application/json;charset=UTF-8’);
xhr.send();
xhr.ontimeout = function () {
initBundle(null);
};

后端ver.json
{
“assets/main”:“3d91d”,
“assets/resources”:“3ef81”
}

这里的原因是你的主包里面大量用了子包的资源,然后主包优先级又比较高,把子包的资源全部拉过去了,你把子包的优先级调整到8。大小就会和以前一样了,但是这个时候主包就会依赖子包了。你必须在游戏启动的时候加载你的子包,这样才不会报错,这是 Asset Bundle 的依赖关系导致的。Asset Bundle 要求对资源目录结构的划分要比以前更清晰,把依赖关系整理好之后。Asset Bundle 带来的优化肯定是要比之前好很多的

你先把你要更新的内置包放在服务器上,然后把bundleRoot改为对应的服务器地址试试,类似下面这样:

let bundleRoot = ["http://xxx.com/assets/resources", "http://xxx.com/assets/main", "http://xxx.com/assets/internal"];

今天又测试一下。发现。Asset Bundle里有场景。我把代码挂到这个场景的一个节点上。代码就不能热更,
但是我挂到Bundle里的一个预设上就可以

内置bundle我在试下先

试了你的方法。还是不能更新

是可以加载。但是更新后。还是老的资源

let bundleRoot = ["assets/internal", "assets/resources", "assets/main"];
var count = 0;
function cb(err) {
    if (err) return console.error(err.message, err.stack);
    count++;
    if (count === bundleRoot.length + 1) {
        cc.game.run(option, onStart);
    }
}
var initBundle = function (version) {
    cc.assetManager.loadScript(settings.jsList.map(function (x) { return 'src/' + x; }), cb);
    for (let i = 0; i < bundleRoot.length; i++) {
        var bundleName = bundleRoot[i];
        var bundleUrl = "http://192.168.68.165:10220/res/" + bundleName;
        var op = null;
        if (version && version[bundleName]) op = { version: version[bundleName] };
        cc.assetManager.loadBundle(bundleUrl, op, cb);
    }
}
var xhr = new XMLHttpRequest();
xhr.timeout = 5000;
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
        var httpDatas = JSON.parse(xhr.responseText);
        initBundle(httpDatas);
    }
    else if (xhr.readyState == 4 && xhr.status == 0) {
        initBundle(null);
    }
};
var url = 'http://192.168.68.165:10220/res/version.json';
xhr.open('GET', url, true);
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
xhr.send();
xhr.ontimeout = function () {
    initBundle(null);
};

};

后端 version.json
{
“assets/internal”: “09c80”,
“assets/resources”: “0250a”,
“assets/main”: “299fb”,
}

你可以在服务器侧看下有没有收到资源请求呢?

测试了下。是没有加载服务器资源,可能是本地缓存了,但是我加了版本号呀

那你断点调试下,,这里传的是对的值么

是的。就是修改资源重新构建后的哈希值,

把你的 main.js 发出来看下?

window.boot = function () {
var settings = window._CCSettings;
window._CCSettings = undefined;
var onProgress = null;

let { RESOURCES, INTERNAL, MAIN, START_SCENE } = cc.AssetManager.BuiltinBundleName;
function setLoadingDisplay() {
    // Loading splash scene
    var splash = document.getElementById('splash');
    var progressBar = splash.querySelector('.progress-bar span');
    onProgress = function (finish, total) {
        var percent = 100 * finish / total;
        if (progressBar) {
            progressBar.style.width = percent.toFixed(2) + '%';
        }
    };
    splash.style.display = 'block';
    progressBar.style.width = '0%';

    cc.director.once(cc.Director.EVENT_AFTER_SCENE_LAUNCH, function () {
        splash.style.display = 'none';
    });
}

var onStart = function () {

    cc.view.enableRetina(true);
    cc.view.resizeWithBrowserSize(true);

    if (cc.sys.isBrowser) {
        setLoadingDisplay();
    }

    if (cc.sys.isMobile) {
        if (settings.orientation === 'landscape') {
            cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE);
        }
        else if (settings.orientation === 'portrait') {
            cc.view.setOrientation(cc.macro.ORIENTATION_PORTRAIT);
        }
        cc.view.enableAutoFullScreen([
            cc.sys.BROWSER_TYPE_BAIDU,
            cc.sys.BROWSER_TYPE_BAIDU_APP,
            cc.sys.BROWSER_TYPE_WECHAT,
            cc.sys.BROWSER_TYPE_MOBILE_QQ,
            cc.sys.BROWSER_TYPE_MIUI,
        ].indexOf(cc.sys.browserType) < 0);
    }

    // Limit downloading max concurrent task to 2,
    // more tasks simultaneously may cause performance draw back on some android system / browsers.
    // You can adjust the number based on your own test result, you have to set it before any loading process to take effect.
    if (cc.sys.isBrowser && cc.sys.os === cc.sys.OS_ANDROID) {
        cc.assetManager.downloader.maxConcurrency = 2;
        cc.assetManager.downloader.maxRequestsPerFrame = 2;
    }

    var launchScene = settings.launchScene;
    var bundle = cc.assetManager.bundles.find(function (b) {
        return b.getSceneInfo(launchScene);
    });

    bundle.loadScene(launchScene, null, onProgress,
        function (err, scene) {
            if (!err) {
                cc.director.runSceneImmediate(scene);
                if (cc.sys.isBrowser) {
                    // show canvas
                    var canvas = document.getElementById('GameCanvas');
                    canvas.style.visibility = '';
                    var div = document.getElementById('GameDiv');
                    if (div) {
                        div.style.backgroundImage = '';
                    }
                    console.log('Success to load scene: ' + launchScene);
                }
            }
        }
    );

};

var option = {
    id: 'GameCanvas',
    debugMode: settings.debug ? cc.debug.DebugMode.INFO : cc.debug.DebugMode.ERROR,
    showFPS: settings.debug,
    frameRate: 60,
    groupList: settings.groupList,
    collisionMatrix: settings.collisionMatrix,
};

cc.assetManager.init({
    bundleVers: settings.bundleVers,
    remoteBundles: settings.remoteBundles,
    server: settings.server
});

let bundleRoot = ["assets/internal", "assets/resources", "assets/main"];
//cc.AssetManager.cacheManager.clearCache();
var count = 0;
function cb(err) {
    if (err) return console.error(err.message, err.stack);
    count++;
    if (count === bundleRoot.length + 1) {
        cc.game.run(option, onStart);
    }
}
var initBundle = function (version) {
    cc.assetManager.loadScript(settings.jsList.map(function (x) { return 'src/' + x; }), cb);
    for (let i = 0; i < bundleRoot.length; i++) {
        var bundleName = bundleRoot[i];
        var bundleUrl = "http://192.168.68.165:10220/res/" + bundleName;
        var op = null;
        if (version && version[bundleName]) op = { version: version[bundleName] };
        cc.assetManager.loadBundle(bundleUrl, op, cb);
    }
}
var xhr = new XMLHttpRequest();
xhr.timeout = 5000;
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
        var httpDatas = JSON.parse(xhr.responseText);
        initBundle(httpDatas);
    }
    else if (xhr.readyState == 4 && xhr.status == 0) {
        initBundle(null);
    }
};
var time = Date.now();
var url = 'http://192.168.68.165:10220/res/version.json?a=' + time;
xhr.open('GET', url, true);
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
xhr.send();
xhr.ontimeout = function () {
    initBundle(null);
};

};

if (window.jsb) {
var isRuntime = (typeof loadRuntime === ‘function’);
if (isRuntime) {
require(‘src/settings.js’);
require(‘src/cocos2d-runtime.js’);
if (CC_PHYSICS_BUILTIN || CC_PHYSICS_CANNON) {
require(‘src/physics.js’);
}
require(‘jsb-adapter/engine/index.js’);
}
else {
require(‘src/settings.js’);
require(‘src/cocos2d-jsb.js’);
if (CC_PHYSICS_BUILTIN || CC_PHYSICS_CANNON) {
require(‘src/physics.js’);
}
require(‘jsb-adapter/jsb-engine.js’);
}

cc.macro.CLEANUP_IMAGE_CACHE = true;
window.boot();

}