天天看點

CocosCreator2.x大項目卡頓終極解決方案:Aswallow

前言

論壇上有很多文章、很多人說Creator大項目卡頓,也在苦苦尋找解決方案。

這對于每一個想用

Creator

做個大項目或者正在做着項目的小夥伴來說都是很難受的。

這可能會讓他們割舍對Creator的喜愛,而另作選擇。

或者在上了車之後,沒法填這個坑導緻項目黃了,那就更加難過了。

怎麼辦呢?我過年時就萌生了一個想法:我想摸一下Creator的上限。看看到底能不能解決大項目卡頓的問題,也是替各位小夥伴們探探路。

前段時間的探索,成功了。

那讓我知道Creator開發大項目是完全沒有問題的。

可以讓我們用Creator爽,一直用一直爽的。

CocosCreator2.x大項目卡頓終極解決方案:Aswallow

文章:

我想摸一下Creator的上限

上個星期有個深陷水深火熱的小夥伴找到我,讓我幫幫忙

CocosCreator2.x大項目卡頓終極解決方案:Aswallow
CocosCreator2.x大項目卡頓終極解決方案:Aswallow

能夠幫到他,非常開心。

CocosCreator2.x大項目卡頓終極解決方案:Aswallow

最近項目趕版本,比較忙,是以解決方案完善的進度慢了些。

雖遲但到~

CocosCreator2.x大項目卡頓終極解決方案:Aswallow

視訊示範:

https://www.bilibili.com/video/BV1hh411e7p5/

插件位址:

https://store.cocos.com/app/resources/search?name=Aswallow

我們感到難受的是什麼?

先說開發過程中讓人感覺很舒服的一種情況

我改了一行代碼,立刻就能看到運作情況

讓人感覺難受的是什麼?

我改了一行代碼,等了好久都沒能運作起來

回報的時間越短,越舒服

CocosCreator2.x大項目卡頓終極解決方案:Aswallow

其實這裡有一個很有趣的概念,叫

即時回報

,它是進入心流狀态的條件之一(就是那種很爽很沉醉的狀态)

有興趣的可以查一下。

CocosCreator

讓我們在開發遊戲過程中,能快速得到回報

  1. 編輯場景,儲存一下就可以重新整理看結果
  2. 改一下代碼,立刻編譯看結果
  3. 修改shader立刻也能看到效果
  4. 遇到難點、bug翻一下論壇就能找到解決方案

這個就很舒服

但項目資源越多,這個改了一行代碼,卡的時間就越長,越來越難受。

而項目後期大部分時間可能都是在改代碼,也就意味着,一直卡。像吃屎一樣。

CocosCreator2.x大項目卡頓終極解決方案:Aswallow

其實。。。

其實很多引擎在項目資源多的時候都會出現卡頓、回報時間長等問題,這個是通病。

有問題就解決嘛。我們先找找原因

另外:

CocosCreator

已經做得很好了,不是嗎?

卡頓的根源:Creator編輯器的資源管理機制

Creator

編輯器會對所有資源進行分析,記錄它們之間的依賴關系。

.meta

檔案就是記錄資源的資訊和依賴資訊

資源的修改、增加、删除,都可能會導緻依賴資訊變化。

是以Creator會監視所有assets目錄下的檔案,當某個資源變動,編輯器都會周遊檢查一下變動的影響。

這是為了保證依賴的準确性,如果依賴缺失了就會立刻提示你。

是以,當資源量多了,這個處理耗時就會變得越來越長。

這也是以下情況的緣由

  1. 儲存一下prefab,卡頓好久
  2. 儲存一下代碼,切回來卡了好久

正所謂成也蕭何敗也蕭何

解決思路:拆

論壇上其實就有這個思路的方案,比如

  1. 将圖檔預先打成圖集=>減少圖檔資源量
  2. 将資源放到CDN

Creator官方在

Creator2.4.x

版本也給出了他們的解決方案:AssetBundle

我覺得,在項目内分AssetBundle,卡頓問題還是沒法解決的。因為資源量沒變,處理耗時也也沒有減少

但如果在另外一個項目制作資源的

AssetBundle

,然後導出。這個是可以解決問題的。

這些方案是有用,但就是有些麻煩,怎麼才能做到更加友善和無感覺呢?

而且還有一個問題,怎麼加載解析

圖集

龍骨

spine

甚至

fgui釋出的資源

tilemap

呢?

因為官方的接口中,加載遠端資源:隻能加載簡單的圖檔、音頻、文本

文檔傳送門🚪:

https://docs.cocos.com/creator/manual/zh/scripting/dynamic-load-resources.html

我的解決方案

拆分資源的解決方案

第一種:自定義網頁預覽

不知道大家知不知道這個的存在。

文檔傳送門:

https://docs.cocos.com/creator/manual/zh/advanced-topics/custom-preview-template.html

在項目根目錄建立

preview-templates

,然後編輯器的預覽功能就會以這個目錄為入口

你将外部資源放到這個檔案夾,使用遠端加載接口,就可以加載到這裡的資源

//直接将someres.png放到preview-templates
var remoteUrl = "someres.png";
cc.assetManager.loadRemote(remoteUrl, function (err, texture) {
    // Use texture to create sprite frame
});
           

但這樣需要自己在建構時處理資源,複制到釋出目錄

第二種:插件 aswallow 如燕(諧音:愛上我咯)

  1. 開發預覽支援

    我通過hook creator的預覽伺服器邏輯,讓你可以通路assets檔案夾外的目錄。對原來的預覽伺服器邏輯無影響

    你隻需将需要拆分出去的資源放到assets檔案夾外的ext-res檔案夾内即可

    這個ext-res也可以通過修改local/aswallow-config.json來修改

  2. 釋出建構支援

    建構時,會自動将資源拷貝到建構輸出目錄,建構配置中的MD5Cache打開可以給檔案名加md5,生成路徑映射version.json檔案

    也可以自己實作自定義的建構處理邏輯,具體可見custom-build-scripts/custom-build.js

    建構功能支援Creator2.3.x和2.4.x,以及釋出建構支援:微信小遊戲(其他小遊戲沒測,應該可以)、安卓原生、web

    當然,如果配合下面的這個運作時會更完美

    ps:聽jare大佬說Assetbundle可以單獨釋出,我沒找到。不過将資源項目釋出到ext-res檔案夾,就可以遠端加載其中的bundle資源了

複雜資源加載解析方案

這個其實挺苦惱的,官方沒有接口。

我在論壇找到了龍骨的加載解析邏輯,然後斷點運作看源碼完善了。圖集、spine、tilemap也是斷點運作看源碼實作的。

找到了解析方法後,基于此實作了

aswallow-asset-manager

它可以讓你更加簡單的加載、解析和管理

外部資源

(圖集、龍骨、spine、tilemap、fgui釋出的資源)

通過加載version檔案,可以實作輕易加載解析加了md5字尾的資源(加載邏輯不變的情況下)

使用示例:

  1. 加載圖集
    aswallow.extAssetMgr.load([{ url: "atlas/emoji", assetType: "plist" }], (err, result) => {
                console.log(result);
                const atlas =  aswallow.extAssetMgr.get("atlas/emoji.plist") as cc.SpriteAtlas;
                console.log(atlas);
                this.emojiSp.spriteFrame = atlas.getSpriteFrame("emoji1")
            });
    }
               
  2. 加載圖檔
    let asset: cc.Asset;
    let index = 0;
    this._scheduleCallback = () => {
        asset = aswallow.extAssetMgr.get(`${iconRoot}/i${index}.png`);
        index = Math.floor(Math.random() * 10);
        this.sp.spriteFrame = null;
    
        this.sp.spriteFrame = new cc.SpriteFrame(asset as cc.Texture2D);
    }
    let iconRoot = "fgui-res/Icons";
    let resPaths = [];
    for (let i = 0; i < 10; i++) {
        resPaths.push(iconRoot + "/i" + i + ".png");
    }
    // cc.assetManager.preloadAny()
    aswallow.extAssetMgr.load(resPaths, (err, result: aswallow.ILoadResult) => {
        if (!err) {
            console.log(`加載成功`)
            console.log(result);
    
            this.schedule(this._scheduleCallback, 1, cc.macro.REPEAT_FOREVER);
    
    
            // this.sp.spriteFrame.ensureLoadTexture();
    
        }
    
    });
               
  3. 加載龍骨
    const extAssetMgr = aswallow.extAssetMgr; 
    extAssetMgr.load([
        { url: "dragonbones/dragon/texture.json", assetType: "DragonBonesAtlasAsset" },
        { url: "dragonbones/dragon/NewDragonTest.json", assetType: "DragonBonesAsset" },
        "dragonbones/dragon/texture.png"], (err, items) => {
        console.log(items)
        this.dragonBone_json.dragonAsset = extAssetMgr.get("dragonbones/dragon/NewDragonTest.json") as any;
        this.dragonBone_json.dragonAtlasAsset = extAssetMgr.get("dragonbones/dragon/texture.json") as any;
        this.dragonBone_json.armatureName = 'armatureName';
        this.dragonBone_json.playAnimation('stand', 0);
    });
    //加載二進制
    
    extAssetMgr.load({ url: "dragonbones/sword-man/SwordsMan", assetType: "DragonBonesAsset", ext: ".dbbin" }, (err, items) => {
        this.dragonBone_bin.dragonAsset = extAssetMgr.get("dragonbones/sword-man/SwordsMan_ske.dbbin") as any;
        this.dragonBone_bin.dragonAtlasAsset = extAssetMgr.get("dragonbones/sword-man/SwordsMan_tex.json") as any;
        this.dragonBone_bin.armatureName = 'Swordsman-NestArmature';
        this.dragonBone_bin.playAnimation('walk', 0);
    })
               
  4. 加載spine
    const extAssetMgr = aswallow.extAssetMgr;
    
    extAssetMgr.load([{ url: "spines/spineboy/spineboy.json", assetType: "SpineAsset" },
                        "spines/spineboy/spineboy.txt",
                        "spines/spineboy/spineboy.png"], (err, items) => {
        console.log(items)
        this.spine_json.skeletonData = extAssetMgr.get("spines/spineboy/spineboy.json") as any;
        this.spine_json.animation = 'run';
    });
    //加載二進制
    extAssetMgr.load([{ url: "spines/spineRatorBin/raptor-pro.skel", assetType: "SpineAsset" },
                        "spines/spineRatorBin/raptor-pro.atlas",
                        "spines/spineRatorBin/raptor-pro.png"], (err, items) => {
        console.log(items)
        this.spine_bin.skeletonData = extAssetMgr.get("spines/spineRatorBin/raptor-pro.skel") as any;
        this.spine_bin.animation = 'walk';
        // this.spine._updateSkeletonData
    });
               
  5. 加載fgui
  6. 資源釋放(以釋放spine資源為例)
    aswallow.extAssetMgr.release([
        { url: "spines/spineboy/spineboy.json", assetType: "SpineAsset" },
        "spines/spineboy/spineboy.txt",
        "spines/spineboy/spineboy.png",
        { url: "spines/spineRatorBin/raptor-pro.skel", assetType: "SpineAsset" },
        "spines/spineRatorBin/raptor-pro.atlas",
        "spines/spineRatorBin/raptor-pro.png"
    ])
               

暫時支援2.4.x,釋出建構測試通過的平台:Android原生、web、微信小遊戲(其他小遊戲平台應該也可以)

最後

CocosCreator其實是很強大的,不是嗎?

卡頓問題也是可以輕易解決的,不是嗎?

希望每個喜愛Cocos的小夥伴不用糾結要不要用Creator開發大項目

希望在開發大項目的小夥伴不再受卡頓之苦

希望每個CocosCreator項目都有所成~

能幫到你們真的很開心。

如果喜歡我的解決方案,想一起玩轉遊戲開發

歡迎關注我的公衆号

公衆号搜尋:玩轉遊戲開發

或掃碼:

CocosCreator2.x大項目卡頓終極解決方案:Aswallow

QQ 群: 1103157878

部落格首頁: https://ailhc.github.io/

掘金: https://juejin.cn/user/3069492195769469

github: https://github.com/AILHC

繼續閱讀