cocos論壇鏈接:https://forum.cocos.org/t/cocoscreator-assetsbundle/88349
///////這里只是自己備注下,做個記錄,下面是論壇原作者原文描述:
assets-bundle插件基於官方的分包策略。
之前完成過另一款分包插件 subpackage-tools 項目上線一年,沒有任何問題。該插件完全基於分包熱更完成。現在插件商店已經看不到它了,插件的核心只是分離資源而已,真正需要在項目中使用,必須要自己完成分包熱更的項目邏輯,所以一直沒有出使用demo,被不少人詬病,汗顏!
官方的分包加載已經基本可以用於原生環境,其中代碼的分包在原生環境App啟動速度上有較大幫助,但是原生資源的分包僅對小游戲環境有降低包體的作用,對原生環境沒有任何作用。
插件在官方分包的策略上 加強了對原生環境的支持: 資源分包插件核心功能:
- 接管官方分包策略
- 追加分離出非原生資源(import資源)
- 對分包追加熱更功能
支持三種分包模式- 本地包: 官方分包
- 熱更包: 在本地包的基礎上對分包最佳熱更功能 使用前先檢查資源版本
- 遠程包: 在熱更包的基礎上將分包從構建項目中分離出來 使用前必須先下載遠程包
插件作用: 降低App包體大小,加快App啟動速度。適用於大廳游戲和關卡游戲
唯一遺憾的事沒能降低setting.js的大小,研究發現資源不放在 resources 目錄下也是可以動態加載的,但是不放在該目錄下又需要動態加載的資源大部分都不會參與項目構建,全部堆在一個場景里倒是可以解決問題,但是明顯不怎么優雅。斟酌后還是放下了對setting.js的手術刀
插件支持自動 zip 壓縮 import 和 raw-assets 目錄
基於 2.3.0版本Mac下開發,目測在 2.x版本都是可以跑的 至於win環境好不好使我就不知道了 ,歡迎提Bug。

插件簡單介紹:
- 所有.manifest文件都放在 assets/resources/Manifest 目錄 插件會完全操作(刪除、寫入)這個目錄,如果沖突請自行轉移目錄內資源
- 生成的子包全部放在 ${project}/HotUpdate/${項目分支}/目錄 同樣是完全操作這個目錄,如果沖突請自行轉移目錄內資源
- 支持Debug模式,啟動該模式 分包會被統一放進 ${project}/HotUpdate/${項目分支}/Debug目錄 對應的遠程熱更地址也會追加 "http://host.com/${項目分支}/Debug"
- 支持包名搜索,當子包較多時可以使用包名搜索功能
- 插件自動和手動校驗子包的資源安全性(是否丟失資源和是否引用了其他私有子包的資源)
- 插件支持自動校驗當前項目的分包設置與插件的分包設置是否一致
- 支持手動清空和設置項目分包
- 支持自動和手動向Manifest目錄中導入遠程分包的空清單文件
- 支持 zip 壓縮子包資源
- 支持三種分包模式
- 如果不設置任何子包 則該插件為一個簡單的熱更插件
- 如果不需要本插件,卸載或者不打開本插件即可
使用方法:
- 編輯器面板->擴展->assets-bundle
- 配置好主包以及子包信息
- 打開構建面板->構建 必須至少構建兩次以上
- 檢查控制台是否有爆紅 如果有,必須要先解決爆紅問題
- 檢測HotUpdate目錄是否生成對應的主包和子包 檢測主包和子包是否完整(初次使用小心點)
- 檢查無誤后,打開AndroidStudio或者xcode編譯App
目前插件已經完成了資源分離的測試,僅初步完成了分包熱更下載的測試
本插件僅是一個項目分包的工具,分包熱更的邏輯代碼請自行根據自身項目完成
沒有demo,完全開源
被第一版插件(subpackage-tools)的地獄回調惡心到了,這版插件采用了 await 寫法,邏輯上清晰一些,但是本次插件的核心邏輯寫在了主線程上,修改代碼會造成編輯器奔潰或插件無法打開的情況
插件剛完成,還是熱乎的。
https://github.com/zPiggy/assets-bundle200
注意
1.插件目前不支持 win 環境使用,非常抱歉,等我找個 win 電腦。。。。 有興趣的朋友可以提交PR
2.插件不支持勾選【內聯所有 SpriteFrame】和 【合並圖集中的 SpriteFrame】
3.目測插件兼容 2.x 版本
///////下面我記錄點使用體會:
使用該插件的CocosCreator版本是2.2.2
使用目標:從項目中把某些實現抽出為prefab資源(不帶js),再動態加載該資源
原作者的方式,應該是走的熱更新思路,把資源熱更新完整后,再進游戲
為了達到動態加載分包資源,對插件做了一些修改,對所有分包分別生成對應的setting.json(格式類似build/jsb-link/src/settings.js)
使用的某個分包時,先把其setting.json追加到settings.js里,在loadSubpackage,再loadRes使用
接入流程
1.把插件放到node_modules下
2.啟動Creator,打開插件面板,設置分包,類型為遠程,設置按鈕都點一遍
3.在插件面板打開的條件下,開始針對ios平台構建
4.會在保存分包資源的目錄下看到分包資源,最后使用的是:分包名的文件
5.客戶端代碼里需要實現資源的下載和移動 到對應位置
6.creator的js引擎engine里需要添加兩個add方法
7.客戶端實現SubpackageManager,實現加載分包配置問題件setting.json和分包資源
8.可以像resources下的資源使用方式一樣使用
動態加載settings.js配置
// .1 引擎修改
pack-downloader.js
addPacks: function (packs) {
Object.assign(packIndices, packs);
for (var packUuid in packs) {
var uuids = packs[packUuid];
for (var i = 0; i < uuids.length; i++) {
var uuid = uuids[i];
// the smallest pack must be at the beginning of the array to download more first
var pushFront = uuids.length === 1;
if (uuidToPack[uuid]) {
if (typeof uuidToPack[uuid] == 'string') {
if (uuidToPack[uuid] != packUuid) {
pushToMap(uuidToPack, uuid, packUuid, pushFront);
globalUnpackers[packUuid] = new UnpackerData();
}
} else if (typeof uuidToPack[uuid] == 'object') {
if (uuidToPack[uuid].indexOf(packUuid) == -1) {
pushToMap(uuidToPack, uuid, packUuid, pushFront);
globalUnpackers[packUuid] = new UnpackerData();
}
}
} else {
pushToMap(uuidToPack, uuid, packUuid, pushFront);
globalUnpackers[packUuid] = new UnpackerData();
}
}
}
},
// .2 引擎修改
CCAssetLibrary.js
add: function (options) {
if (CC_EDITOR && _libraryBase) {
cc.errorID(6402);
return;
}
console.log("CCAssetLibrary ——add",JSON.stringify(options));
// 這里將路徑轉 url,不使用路徑的原因是有的 runtime 不能解析 "\" 符號。
// 不使用 url.format 的原因是 windows 不支持 file:// 和 /// 開頭的協議,所以只能用 replace 操作直接把路徑轉成 URL。
var libraryPath = options.libraryPath;
libraryPath = libraryPath.replace(/\\/g, '/');
_libraryBase = cc.path.stripSep(libraryPath) + '/';
_rawAssetsBase = options.rawAssetsBase;
if (options.subpackages) {
var subPackPipe = new SubPackPipe(options.subpackages);
cc.loader.insertPipeAfter(cc.loader.assetLoader, subPackPipe);
cc.loader.subPackPipe = subPackPipe;
}
var md5AssetsMap = options.md5AssetsMap;
if (md5AssetsMap && md5AssetsMap.import) {
// decode uuid
var i = 0, uuid = 0;
var md5ImportMap = js.createMap(true);
var md5Entries = md5AssetsMap.import;
for (i = 0; i < md5Entries.length; i += 2) {
uuid = decodeUuid(md5Entries[i]);
md5ImportMap[uuid] = md5Entries[i + 1];
}
var md5RawAssetsMap = js.createMap(true);
md5Entries = md5AssetsMap['raw-assets'];
for (i = 0; i < md5Entries.length; i += 2) {
uuid = decodeUuid(md5Entries[i]);
md5RawAssetsMap[uuid] = md5Entries[i + 1];
}
var md5Pipe = new MD5Pipe(md5ImportMap, md5RawAssetsMap, _libraryBase);
cc.loader.insertPipeAfter(cc.loader.assetLoader, md5Pipe);
cc.loader.md5Pipe = md5Pipe;
}
// init raw assets
var assetTables = Loader._assetTables;
// for (var mount in assetTables) {
// assetTables[mount].reset();
// }
var rawAssets = options.rawAssets;
if (rawAssets) {
for (var mountPoint in rawAssets) {
var assets = rawAssets[mountPoint];
for (var uuid in assets) {
var info = assets[uuid];
var url = info[0];
var typeId = info[1];
var type = cc.js._getClassById(typeId);
if (!type) {
cc.error('Cannot get', typeId);
continue;
}
// backward compatibility since 1.10
_uuidToRawAsset[uuid] = new RawAssetEntry(mountPoint + '/' + url, type);
// init resources
var ext = cc.path.extname(url);
if (ext) {
// trim base dir and extname
url = url.slice(0, - ext.length);
}
var isSubAsset = info[2] === 1;
if (!assetTables[mountPoint]) {
assetTables[mountPoint] = new AssetTable();
}
assetTables[mountPoint].add(url, uuid, type, !isSubAsset);
}
}
}
if (options.packedAssets) {
PackDownloader.addPacks(options.packedAssets);
}
// init cc.url
//cc.url._init((options.mountPaths && options.mountPaths.assets) || _rawAssetsBase + 'assets');
}
// .3 實際使用 配置
settings.js一樣的json變量
let settings = {
platform: "ios",
groupList: [
"default"
],
collisionMatrix: [
[
true
]
],
rawAssets: {
assets: {
"81eZ4OBP5K8aodrm0mUeUx": [
"Manifest/GG1/project.manifest",
"cc.Asset"
],
b1mieGwm9AvYveQiL5J9Ua: [
"Manifest/GG1/version.manifest",
"cc.Asset"
],
"63mugu3iZOj48reHFL0PpW": [
"Manifest/GG2/project.manifest",
"cc.Asset"
],
"a7IRMZApZP05+cIjIyYosD": [
"Manifest/GG2/version.manifest",
"cc.Asset"
],
f2WiYLVw1HW62wvwgXkBxf: [
"Manifest/GG3/project.manifest",
"cc.Asset"
],
f3RsjV8FdA0LKiGKFJ4N69: [
"Manifest/GG3/version.manifest",
"cc.Asset"
],
"6e8a2Bt6RD56C+449klPgK": [
"animation/flowers.anim",
"cc.AnimationClip"
],
"2dlpEdpTBG+Ir+siKhVGn9": [
"animation/flowers.plist",
"cc.SpriteAtlas"
],
f1CoDbA31A6oxWDQCh4rJr: [
"animation/flowers.png",
"cc.Texture2D"
],
"98v1T2ow9KirOlKXmERSKB": [
"animation/flowers.prefab",
"cc.Prefab"
],
"588mxohQ9PMIn2SXzlRvSs": [
"other/CloseNormal",
"cc.SpriteFrame",
1
],
dav7r5oUxIA6I8PXxNwrvA: [
"other/CloseNormal.png",
"cc.Texture2D"
],
"4cOT4SRmNNvbiuUbXWfJwC": [
"texutres/content",
"cc.SpriteFrame",
1
],
"43YDW93n1HaponMKBSdm9J": [
"texutres/content.png",
"cc.Texture2D"
],
"15l8P5pThPRpevCrnVQ1x8": [
"texutres/dlrb",
"cc.SpriteFrame",
1
],
"0fG14ZFJBJ/aIEGnJ6D70W": [
"texutres/dlrb.jpeg",
"cc.Texture2D"
],
"79kA4i8eRPj5onAzFCzUHO": [
"texutres/image",
"cc.SpriteFrame",
1
],
"2cQFeyIvFCZ5XSs99fErRi": [
"texutres/image.jpg",
"cc.Texture2D"
],
"7eQ/1cS+5GnokLdeCxfyBj": [
"texutres/wcard",
"cc.SpriteFrame",
1
],
bfxkrin9FK9oONXkkWtJQm: [
"texutres/wcard.png",
"cc.Texture2D"
]
},
internal: {
"14TDKXr2NJ6LjvHPops74o": [
"effects/builtin-2d-gray-sprite.effect",
"cc.EffectAsset"
],
"0ek66qC1NOQLjgYmi04HvX": [
"effects/builtin-2d-spine.effect",
"cc.EffectAsset"
],
"28dPjdQWxEQIG3VVl1Qm6T": [
"effects/builtin-2d-sprite.effect",
"cc.EffectAsset"
],
c0BAyVxX9JzZy8EjFrc9DU: [
"effects/builtin-clear-stencil.effect",
"cc.EffectAsset"
],
"796vrvt+9F2Zw/WR3INvx6": [
"effects/builtin-unlit-transparent.effect",
"cc.EffectAsset"
],
"6dkeWRTOBGXICfYQ7JUBnG": [
"effects/builtin-unlit.effect",
"cc.EffectAsset"
],
"6fgBCSDDdPMInvyNlggls2": [
"materials/builtin-2d-base.mtl",
"cc.Material"
],
"3ae7efMv1CLq2ilvUY/tQi": [
"materials/builtin-2d-gray-sprite.mtl",
"cc.Material"
],
"7a/QZLET9IDreTiBfRn2PD": [
"materials/builtin-2d-spine.mtl",
"cc.Material"
],
"ecpdLyjvZBwrvm+cedCcQy": [
"materials/builtin-2d-sprite.mtl",
"cc.Material"
],
cffgu4qBxEqa150o1DmRAy: [
"materials/builtin-clear-stencil.mtl",
"cc.Material"
],
"2aKWBXJHxKHLvrBUi2yYZQ": [
"materials/builtin-unlit.mtl",
"cc.Material"
]
}
},
launchScene: "db://assets/Scene/helloworld.fire",
scenes: [
{
url: "db://assets/Scene/helloworld.fire",
uuid: "2dL3kvpAxJu6GJ7RdqJG5J"
}
],
packedAssets: {
"020e176f2": [
"02delMVqdBD70a/HSD99FK",
"0fG14ZFJBJ/aIEGnJ6D70W",
"2cQFeyIvFCZ5XSs99fErRi",
"43YDW93n1HaponMKBSdm9J",
"bfxkrin9FK9oONXkkWtJQm",
"dav7r5oUxIA6I8PXxNwrvA",
"f1CoDbA31A6oxWDQCh4rJr"
],
"041f9227c": [
"2dlpEdpTBG+Ir+siKhVGn9",
"7a13M2gK9F3qMGpI+Sc8v8",
"c0fMgQNWFEw5HlwgSQQ7GJ",
"ccRsWQ6LpNk5SbfMaTZyw9",
"d8xyHtt9pDtJ3wvHEZ8Y/x",
"e0UT0oa8BOFK+82UvU/2b6",
"e7wu7ggnpObpJcyfHzwLYo",
"f9fY9cyhZCKbGFPr9RbI1+"
],
"05917af62": [
"7a13M2gK9F3qMGpI+Sc8v8",
"98v1T2ow9KirOlKXmERSKB",
"a2MjXRFdtLlYQ5ouAFv/+R",
"c0fMgQNWFEw5HlwgSQQ7GJ",
"ccRsWQ6LpNk5SbfMaTZyw9",
"d8xyHtt9pDtJ3wvHEZ8Y/x",
"e0UT0oa8BOFK+82UvU/2b6",
"e7wu7ggnpObpJcyfHzwLYo",
"f9fY9cyhZCKbGFPr9RbI1+"
],
"0c204717b": [
"2dL3kvpAxJu6GJ7RdqJG5J",
"a2MjXRFdtLlYQ5ouAFv/+R"
]
},
md5AssetsMap: {},
orientation: "",
debug: true,
subpackages: {
GG1: {
name: "GG1",
path: "subpackages/GG1/",
uuids: [
"f10a80db-037d-40ea-8c56-0d00a1e2b26b"
]
},
GG2: {
name: "GG2",
path: "subpackages/GG2/",
uuids: [
"dabfbaf9-a14c-4803-a23c-3d7c4dc2bbc0"
]
},
GG3: {
name: "GG3",
path: "subpackages/GG3/",
uuids: [
"436035bd-de7d-476a-9a27-30a052766f49",
"0f1b5e19-1490-49fd-a204-1a727a0fbd16",
"2c4057b2-22f1-4267-95d2-b3df5f12b462",
"bfc64ae2-9fd1-4af6-838d-5e4916b49426"
]
}
}
};
// .4 實際使用 代碼
// add assets
cc["AssetLibrary"].add({
libraryPath: 'res/import',
rawAssetsBase: 'res/raw-',
rawAssets: settings.rawAssets,
packedAssets: settings.packedAssets,
md5AssetsMap: settings.md5AssetsMap,
subpackages: settings.subpackages
});
Object.assign(cc.loader.downloader._subpackages, settings.subpackages);
let thiz = this;
cc.loader.downloader.loadSubpackage('GG1', function (err) {
if (err) {
console.log('||load subpackage GG1 fail.');
return console.error(JSON.stringify(err));
}
console.log('||load subpackage GG1 successfully.');
console.log("||start prefab")
cc.loader.loadRes('animation/flowers', cc.Prefab, function (err, prefab) {
if (err) {
console.log("||error prefab")
cc.error(err.message || err);
return;
}
cc.log('||Result should be a prefab: ' + (prefab instanceof cc.Prefab));
console.log("||success prefab")
let prefabNode = cc.instantiate(prefab);
prefabNode.parent = thiz.node;
});
console.log("||end prefab")
});
cc.loader.downloader.loadSubpackage('GG2', function (err) {
if (err) {
return console.error(err);
}
console.log('||load subpackage GG2 successfully.');
console.log("||start image")
cc.loader.loadRes('other/CloseNormal', cc.SpriteFrame, function (err, spriteFrame) {
if (err) {
console.log("||error image")
cc.error(err.message || err);
return;
}
thiz.image.spriteFrame = spriteFrame;
cc.log('||Result should be a sprite frame: ' + (spriteFrame instanceof cc.SpriteFrame));
console.log("||success image")
});
console.log("||end image")
});
