egret白鷺引擎RES資源管理模塊,資源動(dòng)態(tài)加載失效BUG,加載卡死BUG,完美解決方案
?? ? ? ?原文csdn程序員社區(qū),B站中發(fā)布的可能過程不完整和有部分錯(cuò)誤。
https://blog.csdn.net/qq_24829537/article/details/126683179
????我是千里馬,是一位軟件工程師,最近幾天完成了用戶中心全套內(nèi)容設(shè)計(jì)和游戲中大大小小的各種bug處理解決,準(zhǔn)備開始游戲的正式填充,突然想起來還有兩件拋之腦后的事情沒有做。因?yàn)橹耙恢倍际敲β荡蠓较騼?nèi)容設(shè)計(jì)研發(fā),有一些小的bug就直接暫時(shí)性質(zhì)的忽略。
????????剛好,最近幾天比較大的基礎(chǔ)工程都已經(jīng)完工了,所以專門抽出時(shí)間來解決這些小一些的問題,那下面就正式開始這次debug過程吧。
? ? ? ? 這次的任務(wù)是解決白鷺引擎RES資源加載模塊相關(guān)問題,算是引擎的坑。
????????每次進(jìn)入游戲的時(shí)候都會(huì)跑3個(gè)進(jìn)度條,但是其中的問題就是每次讀條都會(huì)有10%-20%的幾率加載卡死,加載卡死就會(huì)導(dǎo)致什么問題呢?導(dǎo)致玩家一直在等這個(gè)加載進(jìn)度條,而難以發(fā)現(xiàn)其實(shí)已經(jīng)卡死了,每次遇到都得重新刷新一下游戲而避免開這10%的中獎(jiǎng)率,所以帶給了玩家很糟糕的體驗(yàn)。
? ? ? ? 之前的解決方案都是給加載界面添加一個(gè)提示語,讓玩家不要一直等,多多刷新

? ? ? ? 這是一個(gè)很棘手的bug,幾率性的觸發(fā)bug,所以我并不能用傳統(tǒng)斷點(diǎn)查來源的debug方式去調(diào)試這個(gè)bug,因?yàn)榭赡苓@次是正常的,下次不正常,我也不知道我這次到底是正常還是不正常,只有跑出來結(jié)果才可以知道正常不正常。
? ? ? ? 所以傳統(tǒng)簡單方便的調(diào)試方式在這里就無效了。
? ? ? ? 最開始應(yīng)該是做什么事情呢?當(dāng)然是應(yīng)該在白鷺論壇,看一看網(wǎng)友們和官方提示是怎么解決的。
?? ? ? ? 根據(jù)官方提示把資源加載線程設(shè)置為1,不用多線程加載就可以避開這個(gè)bug。但是網(wǎng)友開發(fā)者們都表示這是無效的,沒什么作用,當(dāng)然我很早之前也測試了這個(gè)解決方案,沒用,該卡照樣卡。


?這位就是官方,也同時(shí)給出了一個(gè)并不能解決的解決方案修改加載線程為1
RES.setMaxLoadingThread(1)
? ? ? ? 所以后面就正式的開始了這次debug之路。
? ? ? ? 首先我進(jìn)行測試出現(xiàn)這個(gè)bug的頻率,基本上每5次出現(xiàn)1次,頻率算是比較高的。然后我就好奇想看一看加載卡住了,我直接關(guān)閉掉這個(gè)加載界面直接進(jìn)游戲是什么樣子的。
????????場景和郵箱系統(tǒng)變成了這樣

? ? ? ? ?背包系統(tǒng)呢?變成了這樣。

?正常情況應(yīng)該是這樣的



?????????從這里我們就可以發(fā)現(xiàn)一部分事情,這里記為A0事件
一部分資源加載了,一部分資源沒有加載,而且大部分資源都沒有加載。
點(diǎn)擊那幾個(gè)背包的文字還是可以切換頁面的代表游戲業(yè)務(wù)邏輯不受當(dāng)前bug影響。
一部分放在res管理器中配置好的預(yù)先加載的資源都已經(jīng)正常加載并且引擎已經(jīng)使用。
已經(jīng)正常加載進(jìn)緩存的資源可以通過讀緩存的方式使用該資源
????????基本上可以判定為,資源動(dòng)態(tài)加載失效,進(jìn)一步測試,發(fā)現(xiàn)eui資源即時(shí)加載也就是source屬性失效,RES資源管理異步加載RES.getResAsync也失效,不管怎么加載返回都是undefined。
? ? ? ? 所以我們理一下邏輯。
加載完資源的時(shí)候>>>RES資源管理器卡死>>>不觸發(fā)資源加載事件完成>>>卡死在加載頁面
RES資源管理器卡死+不觸發(fā)資源加載事件完成>>>任何資源即時(shí)加載都失效>>>不觸發(fā)資源加載事件完成
? ? ? ? 好了,這里開始就有一個(gè)疑點(diǎn)了,加載完成之前都經(jīng)過了什么關(guān)鍵的事件,首先在出現(xiàn)bug情況的開始頁面,前幾次是可以正常即時(shí)加載資源的。也就是說開始頁面的加載完成回調(diào)一點(diǎn)問題都沒有,并且也可以進(jìn)行資源組加載資源。
? ? ? ? 那為什么后面幾次加載就出這種bug呢?所以我也和這個(gè)bug干上了,就要查出來。我先進(jìn)行對自己代碼檢查。頂層代碼是龍骨頁面展示內(nèi)容,沒有一點(diǎn)問題。

?再往核心看,看封裝起來的我們自己的lib庫框架。

?????????正常的加載也沒什么問題,不過資源加載是調(diào)用另一個(gè)核心庫的。這時(shí)候我就開始懷疑了,是不是說,我們封裝的這個(gè)庫這里資源加載是用了一個(gè)資源組,而每次使用加載函數(shù)都是放一個(gè)資源進(jìn)去,有一些研發(fā)不對應(yīng)導(dǎo)致的問題,不管怎么樣我都試一試,把這次的資源組組改成單個(gè)資源組加載,避免掉這種組處理bug,可能就會(huì)解決這次問題了。
? ? ? ? 然后我就把代碼改成了這樣的單獨(dú)組的加載模式。

? ? ? ? ?然后又測試了幾遍,沒一點(diǎn)用啊,bug出現(xiàn)的幾率也沒變,問題依然存在,那么這就表示和資源組處理導(dǎo)致的bug沒關(guān)系,也就排除了我們后期寫業(yè)務(wù)邏輯代碼導(dǎo)致問題的可能性了。
?所以我就繼續(xù)深入架在egret引擎上的核心庫??纯此鞘裁礃拥臉I(yè)務(wù)邏輯。

?????????core核心庫也表示和自己沒一點(diǎn)關(guān)系,并且把鍋直指egret引擎上的RES資源管理系統(tǒng)本統(tǒng)。到目前為止沒有一點(diǎn)成果。所以我就應(yīng)該換方向。多次觸發(fā)試試。
? ? ? ? 弄成多次觸發(fā),看看是不是和資源加載名字,加載順序,和重復(fù)加載,回調(diào)嵌套,以及作用域有關(guān)聯(lián),所以我寫了一個(gè)這樣的一個(gè)無限回調(diào)地獄屎山代碼。
tubao.Appli.loading.play("preload", () => {
? ? ? ? ? ?tubao.Appli.loading.play("scene5000", () => {
? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene5001", () => {
? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene5002", () => {
? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene5003", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene1000", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene1001", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene1002", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene1003", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene1004", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("preload", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene5000", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene5001", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene5002", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene5003", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene1000", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene1001", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene1002", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene1003", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?tubao.Appli.loading.play("scene1004", () => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ? ? ?}, this);
? ? ? ? ? ?}, this);
? ? ? ?}, this);
????????然后又測試了幾遍,沒一點(diǎn)用啊,bug出現(xiàn)的幾率也沒變,問題依然存在,那么這就表示和資源加載名字,加載順序,和重復(fù)加載,回調(diào)嵌套,以及作用域,沒什么關(guān)系。
? ? ? ? 后面我做的第一步是什么,我確定下來有兩個(gè)點(diǎn),這兩個(gè)是外面可以監(jiān)聽到的,所以我就這樣先把加載過程都輸出下來,包括每個(gè)資源加載的回調(diào)結(jié)果,每個(gè)資源組加載開始點(diǎn)和結(jié)束點(diǎn)確定下來。
結(jié)果是這樣的?

????????這張圖告訴了我們什么呢?加載開始沒問題,加載過程沒問題,資源加載流程回調(diào)沒問題,加載完成也沒問題,手動(dòng)關(guān)閉沒問題,加載完成觸發(fā)事件也沒問題,問題是出在了那里呢?就出在了開始加載的時(shí)候。
? ? ? ? 綜合起來前面的一大堆測試結(jié)果,又是一波推理分析。順便整合一下。
只要結(jié)果任何一次資源組加載完成且開始第二個(gè)資源組加載的時(shí)候
那么必然就有
20%幾率導(dǎo)致動(dòng)態(tài)資源加載功能失效
因此導(dǎo)致
就導(dǎo)致沒辦法讓第二個(gè)資源組加載資源
因此導(dǎo)致
加載卡死不動(dòng)
????????第一個(gè)資源組已經(jīng)加載完成且觸發(fā)回調(diào),卡死第二個(gè)資源組資源加載之前,沒有加載第二個(gè)資源組中的任何資源的時(shí)候觸發(fā)了bug,這代表了什么事情,已經(jīng)第三次了,都說我寫的代碼沒問題,是白鷺引擎底層那邊有問題。
? ? ? ? 好,那我就進(jìn)真正的底層去看一看。
? ? ? ? 為此我做了一些微小的工作,當(dāng)然你不用做。
進(jìn)白鷺引擎5.2.30版本核心部分源碼中assetsmanager模塊的復(fù)制下來
把編譯管理文件egretProperties.json中的編譯默認(rèn)配置res管理器編譯庫的工作撤銷下來。
進(jìn)我的代碼里面的lib庫中把官方的res管理器代碼刪除
把剛剛復(fù)制的引擎源碼核心粘貼到src編譯目錄中。
清理引擎,清理項(xiàng)目,處理掉wing 也就是vs code中編譯緩存這些避免后面編譯報(bào)錯(cuò)最終沒辦法開始愉快地玩耍。
? ? ? ? 直接去編譯白鷺源碼,直接看ts代碼,直接下斷點(diǎn)調(diào),這樣便于我后面的調(diào)試。順便我直接就給白鷺源碼寫一些注釋流程。
? ? ? ? 白鷺引擎資源管理模塊有好幾個(gè)接口類配置類這些,不太重要,首先我是做了一部分基礎(chǔ)的測試和閱讀代碼,也有看官方文檔參考,這部分比較無聊就不說了。比較核心的部分就在ResourceLoader里面。
????????后面閱讀代碼debug重點(diǎn)是正常和錯(cuò)誤情況的對比、加載單個(gè)資源過程。
????????當(dāng)然我也不可能預(yù)知到這次是成功還是失敗,所以我準(zhǔn)備了測試代碼,流程就是
我先手動(dòng)刷新
刷出錯(cuò)誤情況和正確情況
依靠自帶eval調(diào)試去這種方式調(diào)試
不過在此之前我必須關(guān)閉掉我框架的安全類,這個(gè)是關(guān)閉的,
????????沒問題了。測試代碼就是
? ? ? ?RES.loadGroup("preload"); ? ? ? ?//資源組加載測試代碼
? ? ? ?RES.getResAsync("daodao2_png"); ? ? ? ?//單個(gè)資源異步加載測試代碼
? ? ? ? ?一部分無聊的調(diào)用過程就略過了,直接說比較關(guān)鍵的部分,這是加載隊(duì)列

?????????資源管理系統(tǒng)拿到加載信息列表,這里基本上已經(jīng)分為了單個(gè)資源加載,最終所有類型方式的加載都變成單個(gè)資源的加載,這是沒問題的
? ? ? ? list是列表的資源組配置,groupname就是組名字,其他也不重要。
? ? ? ? 業(yè)務(wù)邏輯做的事情首先判斷是否已經(jīng)異步加載過這個(gè)資源,加載過就不進(jìn)行加載直接返回資源給你就搞定了。否則就進(jìn)行一波資源加載。
? ? ? ? total表示資源加載的數(shù)量。并且下面進(jìn)行整理資源組名字歸類。等等操作,然后下面建立一個(gè)異步函數(shù)開始剛剛處理好的加載,其中監(jiān)聽加載完成和監(jiān)聽錯(cuò)誤,加載完成回調(diào)resolve事件內(nèi)容返回。然后關(guān)鍵的代碼就是

????????后面我也測試了資源異步加載, 過程不描述了,無聊的各個(gè)層級回調(diào),以及不同資源測試,最終繞來繞去都?xì)w到了這個(gè)函數(shù)里面,這個(gè)摸底基本上花了我3個(gè)小時(shí)的時(shí)間,所以現(xiàn)在的重點(diǎn)就是看loadNextResource這個(gè)函數(shù)的問題。
? ? ? ? 按照正常情況異步資源加載都應(yīng)該返回資源本身就像這樣返回一個(gè)紋理,或者mp3音樂,mp4視頻。

?????????但是他不管幾次加載都返回undefined。看這里的代碼問題。所以后面頭腦就清凈了很多,直接看這個(gè)關(guān)鍵的函數(shù)內(nèi)容就可以了,也可以看見這個(gè)關(guān)鍵的函數(shù)被各個(gè)加載方式最終調(diào)用,前面不管遇到什么困難就都不用管了。

經(jīng)過2天調(diào)試努力
下面就是正常情況和不正常情況區(qū)別開始了
我們可以看見一個(gè)循環(huán),兩個(gè)變量,那個(gè)函數(shù)當(dāng)然也是關(guān)鍵函數(shù)了,不過在這里已經(jīng)不重要,里面是具體加載過程,我們不用太專注的了解。但是我們需要好好了解這兩個(gè)變量,先看結(jié)果
????????錯(cuò)誤的情況是這兩個(gè)變量為錯(cuò)誤false狀態(tài)一直沒辦法加載,兩個(gè)值都是1,1<1,這顯然是錯(cuò)誤的,一直處于跳過狀態(tài)
? ? ? ? 正確的情況是這兩個(gè)變量一個(gè)數(shù)值是不斷變化的,這樣就導(dǎo)致可以產(chǎn)生為true,然后就可以運(yùn)行這個(gè)關(guān)鍵的加載函數(shù)了
?要說原理還是得看這個(gè)關(guān)鍵函數(shù),關(guān)鍵函數(shù)里面干了一件對這次debug很重要的事情,那就是對loadingCount 進(jìn)行遞加和遞減,遞加完必定會(huì)有一次遞減追平。最終趨向0,而thread必定又是一個(gè)固定的數(shù)字且必定極限要比loadingCount大,所以沒問題。
? ? ? ? 那么下面揭秘這兩個(gè)到底是一個(gè)什么變量吧,也是后面我才研究明白的,thread是我們用RES.setMaxLoadingThread設(shè)置的加載線程數(shù),而loadingCount則是當(dāng)前正在加載的資源數(shù)量。
? ? ? ? 這說明了什么呢?
? ? ? ? 想要修復(fù)無法即時(shí)加載資源的bug,和后面無法加載資源的bug,只需要將thread設(shè)置的大一點(diǎn),也就是RES.setMaxLoadingThread設(shè)置的加載線程數(shù)多一點(diǎn),這樣就不會(huì)很容易卡死了,加載速度也更快一些。容錯(cuò)率更高一些
? ? ? ? 而官方告訴我們的加載卡死的解決方案是設(shè)置線程數(shù)為1,這必然就會(huì)導(dǎo)致資源加載隱患失誤,一次資源加載這里沒有減回去追平,就會(huì)卡死。這個(gè)幾率可能是20%,如果我們按常規(guī)4次走呢?0.8%,不到1%的觸發(fā)幾率。
? ? ? ? 畢竟官方這么大引擎,一點(diǎn)點(diǎn)小的疏忽也是很正常的。
????????那么后面就是調(diào)試第二個(gè)問題,加載到90% 100%卡死的問題,不過這個(gè)bug我目前還沒有開始測試,現(xiàn)在就開始測試了。
? ? ? ? 加載到90%卡死

? ? ? ? 首先開始測試觸發(fā)幾率,大概15次觸發(fā)一次卡死。流程輸出結(jié)果

????????從圖中可以看到第一個(gè)加載沒問題,回調(diào)沒問題,問題出在第二個(gè)加載上,開始加載沒問題,加載事件回調(diào)也沒問題,但是只有加載到第6個(gè)的時(shí)候觸發(fā)該bug,第七個(gè)無法加載完成,且沒有回調(diào),然后卡死,第七個(gè)加載的資源是什么呢

?????????沒有一點(diǎn)問題,資源配置沒有問題,問題基本上指向了引擎本身代碼。又是一次翻引擎的debug了。
? ? ? ? 那么第七個(gè)資源真的是沒有加載完成嗎?還是加載完成沒有回調(diào)呢?來一波測試代碼
RES.getResAsync("scene1002_10_png");
? ? ? ? 通過這個(gè)代碼測試下異步返回包含結(jié)果就知道了,如果是texture紋理就表示資源加載完成但沒有觸發(fā)回調(diào)進(jìn)度從而導(dǎo)致卡死,如果是undefined就說明資源加載中卡死。從而卡死在加載界面。
????????
????????是資源加載完成但沒有觸發(fā)回調(diào)進(jìn)度從而導(dǎo)致卡死。這表示了什么呢?資源加載過程沒有一點(diǎn)問題就在觸發(fā)加載流程回調(diào)時(shí)候出問題了。
? 所以我想還是先看一看loadNextResource是否在無盡加載循環(huán)中卡死。
? ? ? ? 直接下斷點(diǎn),沒有進(jìn)入debug的模式暫停,這就表示不是流程加載過程問題導(dǎo)致的卡死。而是在于一些其他方面,那么我對于loadingCount的值應(yīng)該檢查一波。如果loadingCount為大于0的數(shù)字,那么他就表示了這次加載卡死和線程加載過程錯(cuò)誤有關(guān),反之亦然。
? ? ? ? 我該如何拿到loadingCount呢?私有變量我們eval調(diào)試是拿不到的。

? ? ? ? 唯有再加載一個(gè)資源的時(shí)候才能看到,因?yàn)榧热患虞d卡死了那么這個(gè)數(shù)據(jù)就一定會(huì)殘留下來,不會(huì)自動(dòng)重置,那么我們就再加載一個(gè)資源但是加載又有一個(gè)驗(yàn)證。加載一個(gè)沒有加載過在緩存中的資源就可以進(jìn)行驗(yàn)證這個(gè)問題了。而且也不用前面重置底層緩存邏輯內(nèi)容,這樣就麻煩了一點(diǎn),那么我們開始,首先保持上面的斷點(diǎn),然后上測試代碼。
RES.getResAsync("map5003_png");
? ? ? ? 我很清楚的知道m(xù)ap5003這個(gè)資源是絕對沒有加載過的可以放心大膽的測試

? ? ? ? ?很好,已經(jīng)被debug暫停了

?????????loadingCount竟然會(huì)是一個(gè)1而不是0,因前面動(dòng)態(tài)資源加載失敗的測試結(jié)論,這樣固然就會(huì)導(dǎo)致第二個(gè)bug加載到99%卡死,意料之中。
? ? ? ? 但這又代表了什么呢?,我們必須剖析加載時(shí)業(yè)務(wù)邏輯,理清楚加載時(shí)處理。loadSingleResource核心加載函數(shù)干的事情。
? ? ? ? 繼續(xù)挖~
? ? ? ? 所以后面我直接寫注釋在res資源管理模塊。

dic中內(nèi)容是?

?this.loadResource(r)傳入加載正式加載。

?????????閱讀代碼閱讀到這里,有了一個(gè)很興奮的成果了,感謝egret白鷺引擎有記錄日志的好習(xí)慣,只要觸發(fā)加載成功就會(huì)追平,同時(shí)刪除加載時(shí),默認(rèn)情況dic是沒有內(nèi)容的,但是出錯(cuò)這個(gè)日志記錄就有內(nèi)容,所以我只需要看一下dic中的內(nèi)容是什么就可以了,就知道是什么原因?qū)е碌募虞d卡死了。
? ? ? ? 就是這個(gè)mp3文件,寫入名字是加載配置根目錄加名字作為key的,我的資源加載目錄中也沒有這個(gè)文件,當(dāng)然沒辦法加載成功了

? ? ? ? 但我需要關(guān)鍵驗(yàn)證的內(nèi)容是什么呢?
? ? ? ? 這個(gè)真的是url加載目錄名字嗎?不一定,為什么不一定呢?根目錄+文件名字肯定不是真正的文件所在的目錄了,這里還是要感謝一下egret白鷺引擎,白鷺引擎的工程師把兩個(gè)重要信息告訴了我們,第一個(gè)資源配置文件名字和資源名字告訴我們了。?所以下面我們整理一下邏輯內(nèi)容:
? ? ? ? 1.加載的資源位于resource資源配置組
? ? ? ? 2.加載沒有追平也就是加載過程中出現(xiàn)錯(cuò)誤的文件是BGM_1002.mp3
????????我們知道了這個(gè)資源加載失敗了并沒有觸發(fā)回調(diào)追平,而這個(gè)資源加載過程中發(fā)生了什么,我們不得而知。
? ? ? ? 這里的可能性有很多,網(wǎng)絡(luò)波動(dòng),交換機(jī)失靈,更底層的網(wǎng)絡(luò)bug,阿帕奇,nginx服務(wù)器的靜態(tài)資源處理,底層問題。
????????這時(shí)候我們需要做的事情就是跑測試代碼看一看這個(gè)加載失敗的資源是否已經(jīng)緩存入內(nèi)存,如果緩存入內(nèi)存表示是之前加載是成功的只不過沒有觸發(fā)回調(diào)罷了,加載過程沒毛病這是回調(diào)部分出了毛病,如果返回是undefined則表示在開始加載的時(shí)候就有了問題。
? ? ? ? 上測試代碼
RES.getRes("BGM_1002_mp3");
? ? ? ? 我們不用之前常用的RES.getResAsync,這樣避免eval前端ide污染案發(fā)現(xiàn)場。

????????好的,很棒棒結(jié)果是undefined,于是乎有了,網(wǎng)絡(luò)波動(dòng),交換機(jī)失靈,更底層的網(wǎng)絡(luò)bug,阿帕奇,nginx服務(wù)器的靜態(tài)資源處理,等等底層問題。
? ? ? ? 也證明了一件事情白鷺引擎研發(fā)團(tuán)隊(duì)有可能也是受害者。
? ? ? ? 目前距離真相越來越近了,但是很可惜我并不是太懂nginx這些...
? ? ? ? 目前進(jìn)度貌似卡住,還是先看一看這個(gè)文件到底怎么樣,是不是文件本身壞了
? ? ? ? 剛剛測試音樂沒問題

????????讓我們確定一下白鷺的服務(wù)器環(huán)境是什么,這個(gè)一般只需要一個(gè)http報(bào)文就可以確定下來,還是比較簡單的,我在瀏覽器開黃蟲子debug,然后監(jiān)聽網(wǎng)絡(luò)請求。然后隨便找一個(gè)資源去加載。

并沒有結(jié)果,我們看一看錯(cuò)誤請求,看上去是白鷺自己搭建的服務(wù)器環(huán)境。

?所以我們扒開返回html內(nèi)容看一看,我發(fā)現(xiàn)了錯(cuò)誤請求中竟然有一個(gè)隱藏的div標(biāo)記

讓我們看一看這個(gè)svg圖片是什么 ,直接把svg粘貼到一個(gè)文本文檔中然后改名用html查看,ai ,false查看也可以但是沒什么必要了。
svg內(nèi)容就是這個(gè)。
????????這可能是表示白鷺引擎重寫了這個(gè)服務(wù)器工具所以隱藏了這個(gè)錯(cuò)誤提示。也有可能是我瀏覽器安裝插件注入的內(nèi)容。 這個(gè)分支基本上到盡頭了,返回頭看源碼
? ? ? ? 所以我有了一個(gè)猜想,如果再加載一遍這個(gè)mp3文件會(huì)怎么樣?通過異步處理加載sync,如果加載成功表示這次加載失敗是一件底層的幾率處理錯(cuò)誤事件,如果加載失敗就表示是我們源碼處理問題,和底層沒關(guān)系,和白鷺引擎有沒有關(guān)系就看這一次測試了,上測試代碼。
RES.getResAsync("BGM_1002_mp3");
? ? ? ? 這個(gè)一般需要跑兩次,第一次加載,第二次回調(diào)

????????測試了3次 ,結(jié)果是undefined,表示是我們源碼處理問題,和底層沒關(guān)系,是我們和白鷺引擎這邊的問題,為什么你就加載不了呢?在核心加載下斷點(diǎn)調(diào)試

?????????成功釣魚上來

?????????這個(gè)資源加載因?yàn)橐呀?jīng)被記錄入緩存。所以這里就直接從緩存取出來異步返回給調(diào)用者,而異步呢?里面是空的沒內(nèi)容是undefined自然返回undefined表示加載失敗。
? ? ? ? 但是他為什么會(huì)把加載失敗的存入緩存呢?,還有上面的scene1002很怪異,里面也是undefined,為什么名字不是按常理出牌根+文件資源名字而是去后綴名的文件名字。
? ? ? ?這時(shí)候可能就需要更多常規(guī)的測試了,測試正常情況下緩存存入什么,和promisehash到底是什么內(nèi)容。
? ? ? ? 強(qiáng)行翻譯一波
看一看調(diào)用
????????初始為空, 寫入點(diǎn)有兩個(gè)。
? ? ? ? 正常加載操作寫入
? ? ? ? 組加載中寫入一波
????????基本上明白了,這個(gè)研究分支是錯(cuò)誤的,有一個(gè)叫scene1002的資源組。這個(gè)只不過是加載資源組寫入一下 。同時(shí)也是卡住的這個(gè)資源加載組。
? ? ? ? 我們回到原處繼續(xù)分析。
? ? ? ? 有這個(gè)哈希記錄了自然就不會(huì)再次的進(jìn)行加載邏輯了,既然有了一次觸發(fā)加載那么必然直接返回這個(gè)異步加載就可以了。但是這個(gè)異步加載是錯(cuò)誤的,自然直接給你返回undefined。同時(shí)有一個(gè)刪除點(diǎn),這是關(guān)于組的刪除點(diǎn)。
?????????那么進(jìn)一步的debug過程是怎么樣的呢?
????????
?????????第一個(gè)是當(dāng)前異步狀態(tài),第二個(gè)是當(dāng)前異步值,這里表示是等待處理的狀態(tài),異步卡死
? ? ? ? 我把代碼這部分核心的代碼已經(jīng)閱讀翻譯完成了?,看紅框的部分,只要異步加載成功就會(huì)處理追平,并且發(fā)出事件,刪除dic,刪除hash,發(fā)出完成事件。
? ? ? ? 打了一場太極拳,問題又從我們和白鷺引擎的原因回到了網(wǎng)絡(luò)波動(dòng),交換機(jī)失靈,更底層的網(wǎng)絡(luò)bug,阿帕奇,nginx服務(wù)器靜態(tài)資源處理,等等底層問題。
? ? ? ? 剛好我的電腦剪貼板也出了問題,不能復(fù)制粘貼內(nèi)容,這個(gè)很難受,也沒辦法備份,調(diào)試也差不多結(jié)束了,最終歸結(jié)原因就是資源加載問題,我重啟電腦后繼續(xù)調(diào)試觸發(fā),用瀏覽器環(huán)境配合上黃蟲子debug去糾出來加載錯(cuò)誤原因,等等內(nèi)容糾出來最終問題所在。
? ? ? ? 后面的debug計(jì)劃是什么呢?按20%的觸發(fā)幾率在瀏覽器環(huán)境黃蟲子debug下復(fù)現(xiàn)。然后看資源到底是成功加載還是沒有成功加載。先寫一波測試代碼
console.log(this.loadingCount, this.itemLoadDic)
? ? ? ? 這行代碼可以向我們展示當(dāng)前加載狀態(tài)。然后就是一直刷新游戲,刷出來bug。
????????但是我遇到的問題是我刷新游戲了40多次沒有觸發(fā)一次,是不是這個(gè)bug在真實(shí)用戶客戶端這里已經(jīng)解決了。觸發(fā)幾率已經(jīng)是小數(shù)點(diǎn)后兩位以下了,也就是0.025%觸發(fā)幾率
? ? ? ? 這里說明了一個(gè)結(jié)果,那就是客戶端問題導(dǎo)致的資源加載失敗。bug原因打太極又推回到了我們和白鷺引擎這邊,這也是沒辦法了,我也沒辦法預(yù)料是不是在其他類型客戶端會(huì)復(fù)現(xiàn)出來,所以我寫一個(gè)補(bǔ)丁代碼,資源加載到98%就關(guān)閉加載界面。把幾率拉到更低0.00000就可以了。
? ? ? ? 可能這就是最終的處理結(jié)果了。
? ? ? ? 皆大歡喜,兩個(gè)問題基本上都解決了,寫了差不多9000字,這可能是我寫過最長的debug調(diào)試文章了。
? ? ? ? 我是千里馬,也歡迎大家訪問我們的兔寶世界文化創(chuàng)意產(chǎn)品
? ? ? ? 敬請關(guān)注兔寶核芯框架
? ? ? ? 我是千里馬