Creator2.4 推出了AssetBundle,使得全部平臺都有了分包的能力。那麼該如何使用這個強大的功能呢?下面介紹一下我我的的用法,僅供參考,水平有限,非喜勿噴。
根據官方文檔 指出,以前的cc.loader 須要用cc.resource替換
而cc.resource 自己就是一個Bundle
也就是說,2.4以前,整個引擎只有一個cc.loader 管理資源,2.4以後採用了多個Bundle來管理資源,只是cc.resource這個Bundle負責管理resource目錄下的動態資源,已是引擎規定好的了。而自定義的Bundle實際上是與cc.resource平級的。那麼只要咱們給資源管理器傳入不一樣的Bunlde,天然就是加載不一樣Bundle中的內容了。緩存
在介紹個人用法以前,先說明如下幾個概念微信
import ResLoader from "../../cfw/res/ResLoader"; import AudioManager from "../../cfw/audio/AudioManager"; import ResHelper from "../../engine/ResHelper"; import { isNull } from "../../cfw/tools/Define"; export default class Module { private loader: ResLoader; protected audio: AudioManager; protected moduleName: string = '' protected projectName: string = '' constructor(projectName: string, moduleName: string) { this.projectName = projectName; this.moduleName = moduleName; //有名稱的模塊,須要在適當的時候加載bundle 並設置。 if (!this.moduleName) {//name != '' 的 說明是自定義的bundle。 this.setLoader(new ResLoader(new ResHelper(cc.resources))) } } setAudio() { if (this.loader) { this.audio = new AudioManager(this.projectName, this.loader) } } hasLoader() { return !isNull(this.loader) } setLoader(loader: ResLoader) { this.loader = loader } setLoaderByBundle(bundle: cc.AssetManager.Bundle) { this.setLoader(new ResLoader(new ResHelper(bundle, this.moduleName))) } getName() { return this.moduleName; } getLoader() { return this.loader; } getAudio() { return this.audio; } }
import Module from "./Module"; import XlsxDataManager from "../../cfw/xlsx/XlsxDataManager"; import { ResType } from "../../cfw/res/ResInterface"; import ResItem from "../../cfw/res/ResItem"; //模塊id export enum ModuleID { PUBLIC, LOGIN, BATTLE, LOBBY, MAX } //有分包的模塊就有bundle的名字,沒有就是使用cc.resource let moduleName: string[] = ['', '', 'battle', ''] export default class ModuleManager { private static mgrMap: Module[] = [] private static moduleID: ModuleID = ModuleID.PUBLIC; static dataManager: XlsxDataManager; static init(projectName: string) { for (let index = 0; index < moduleName.length; index++) { this.mgrMap[index] = new Module(projectName, moduleName[index]); } this.mgrMap[ModuleID.PUBLIC].setAudio() this.dataManager = new XlsxDataManager() } static getAudio(id: ModuleID = this.moduleID) { return this.mgrMap[id].getAudio() } static publicAudio() { return this.mgrMap[ModuleID.PUBLIC].getAudio() } static publicLoader() { return this.mgrMap[ModuleID.PUBLIC].getLoader() } static loadRes(url: string, type: ResType, callback: (err: string, res: ResItem) => void) { this.getLoader().loadRes(url, type, callback) } static getName(id: ModuleID = this.moduleID) { return this.mgrMap[id].getName() } static setLoaderByBundle(id: ModuleID = this.moduleID, bundle: cc.AssetManager.Bundle) { this.mgrMap[id].setLoaderByBundle(bundle) } static setModuleID(id: ModuleID) { this.moduleID = id; } static getLoader(id: ModuleID = this.moduleID) { return this.mgrMap[id].getLoader() } static hasLoader(id: ModuleID = this.moduleID) { return this.mgrMap[id].hasLoader() } /** * 爲某個模塊設置bundle * @param moduleID * @param callback */ static loadBundle(moduleID: ModuleID, callback: Function) { this.publicLoader().loadRes(ModuleManager.getName(moduleID), ResType.AssetBundle, (err, item: ResItem) => { if (err) { return; } ModuleManager.setLoaderByBundle(moduleID, item.getRes()) callback(); }) } }
資源管理器 ResLoader
負責加載資源
框架
資源項: ResItem 負責管理資源的引用計數
學習
ResHelper
爲了跨引擎使用ResLoader,我自定義了ResType枚舉、ResInterface 接口和這個Creator加載輔助類ResHelper,若是不涉及到跨引擎的話,能夠去掉這幾個東西,而後直接把AssetBundle傳到ResLoader中使用。
ui
若是是resource中的資源做爲bundle以後,須要從resource中拿到外邊。
this
發佈小遊戲時壓縮類型設置爲小遊戲子包,官方文檔已說明
url
看到論壇對於2.4的引用計數問題討論的很是激烈。
https://forum.cocos.org/t/2-4-0/95076/32
我作的資源管理器有以下規則3d
全部資源必須經過資源項ResItem的getRes接口得到,保證使用一次計數增長一次,不參與引擎提供的計數管理。因爲引擎本身管理的依賴關係,因此2.4以後再也不須要維護資源的依賴關係。只維護好本身的使用次數就好。
code
ResLoader 提供刪除某個資源的功能,應對ui清理需求。若是刪除整個模塊,調用release 接口便可。
blog
ResLoader 支持直接緩存一個掛載到場景中的資源,好比初始場景會直接掛載一個預製體,避免黑屏。若是不想清理場景只想清理這個預製體就能夠這樣使用。
實際應用可能複雜的多,每一個人的用法不一樣,不保證沒有問題。
以上各類方案僅是我我的的使用方式,並不是最佳方案,可能會有bug,僅供你們參考,誰有更好的方式,也分享出來,互相學習。
demo 在個人框架項目中,已經更新到2.4。因爲以前忽略文件的緣由,請使用空文件夾從新clone。
歡迎掃碼關注公衆號《微笑遊戲》,瀏覽更多內容。