Cocos2dx-lua中資源熱更新


  項目選擇C++ 和 lua 混合, 看中的就是lua代碼的熱更新優勢,想想之前客戶端出現了bug,需要玩家重新下載安裝包,這帶來的流失率是挺高的; 而隨着現在app體積日益增大,動輒幾十兆、上百兆的安裝包重復下載,對用戶體驗是非常不友好的;另外appstore的審核也是嚴格、標准可變的,很容易審核被拒,導致應用的問題無法及時修復。而選擇lua做為開發語言,就能做到幾乎無感知的修復、增加應用的新功能,對於開發者可以及時修復問題,而對於玩家來說則能獲得更好的游戲體驗。從某狐剛推出某耀客戶端項目,客戶端購買、咨詢量激增來看,這個功能還是很有吸引力的。

  熱更新方案,一開始的設計是單文件更新,思路是:

  1、打包的時候利用腳本對全部的資源文件:包含lua腳本、游戲的圖片、音頻資源生成一份版本文件

  2、客戶端啟動的時候從服務器下載版本文件,跟本地的版本文件進行對比,生成更新列表,然后進行更新

  上述方案的優勢在於:

  1、資源服務器只需要存一套資源文件、

  2、不用考慮客戶端版本與服務器版本之間差異過大,導致數據不對等的問題

  3、方案實現簡單,使用的成本也低,可以實現一些取巧操作(資源服務器直接改某個文件的差異值,讓客戶端直接更新等)

  但是在實際的使用過程中也發現了該方案存在不足:如果待更新的資源過多,那么就會產生大量的http請求,嚴重的影響了下載體驗,而且單個文件的更新失敗,需要一個非常復雜的斷點續傳的方案來控制整體更新。

  在這里提一下一般客戶端實現的文件下載功能:利用curl庫,發起請求進行文件下載。這就會引發兩個問題:請求量及請求響應。上述方案的核心點是根據版本文件生成差異列表,然后再單獨下載差異列表中的每個文件,所以每下載一個文件,就會發起一次請求,如果某次更新有上千個文件,那么單個客戶端更新所發起的請求量將是巨大的。上千次請求,引發上千次的響應等待,對帶寬及玩家的等待時間都將產生巨大的影響!

  因此我們需要新的更新方案:更新是對差異文件進行更新,之前將差異對比放在了客戶端處理階段,那么可以將差異對比放在更新包生成的階段,將版本間的差異文件提取出來,合並成一個壓縮包,客戶端直接下載這一個壓縮包再解壓,實現功能的更新。我們將這個方案稱為差異包更新

  實現這個方案,需要考慮到:

  1、客戶端每次只下載一個文件,需要嚴格保證下載到正確的資源

  2、客戶端更新存在版本延時的問題,需要有跨版本的差異包

1、嚴格保證資源的正確下載

  (1)網絡不穩定的處理:

  手機客戶端考慮到移動網絡的不穩定,容易導致斷網、超時的問題。前面提到的單文件更新方案,在更新的過程中單個文件下載失敗,需要一套非常復雜的斷點續傳方案,才能控制好整體的功能更新,我們是非常粗魯的直接重新下載。。。調整到下載壓縮包之后,就可以很方便的利用curl庫提供的功能,來實現斷點續傳功能:

curl_easy_setopt(_curl, CURLOPT_RESUME_FROM, localLen)

  核心就是上述代碼,CURLOPT_RESUME_FROM, 表示從參數3的位置來寫入本地文件,而參數3的值也很容易獲取,直接使用引擎的getDataFromFile方法getSize就能拿到當前階段本地文件的大小。

  (2)差異包更新失敗的處理:

  之前的單文件更新方案,假如存在錯誤,可能也只是單個文件或單獨幾個文件出現問題,修復比較方便。但是在差異包更新方案中,每次的更新是單個壓縮包的更新,就會存在:

  a.壓縮包下載失敗導致客戶端出現重大功能異常

  b.版本與版本之間生成了錯誤的差異列表導致更新異常

  c.客戶端資源版本不統一,如何下載到統一的更新包

  我們的應對方案是:保留單文件更新功能,在壓縮包下載失敗時進行單文件更新;采用更可靠的生成文件差異值的方案,由一台設備統一生成更新包,針對不同版本生成不同的差異包。

2、更可靠的差異生成方案:

  在上面有提到,差異列表生成錯誤、客戶端版本有差異兩個問題,在這里具體談一下采用一套更可靠的差異生成方案:

  (1)差異值的生成:

  在單文件更新方案里,我們是簡單的對文件大小進行MD5處理,得到一個差異值,然后更新對比中對md5值進行對比,生成差異列表。這個方案就有很大的概率出現md5值一致,但是實際卻需要更新的情況,因此我們改用獲取文件的修改時間,這樣就大大降低了上述情況出現的概率了。

  (2)差異包的生成:

  差異值的獲取,差異包的生成, 在這里講一下思路。這里舉個例子說明客戶端版本差異:客戶端A的當前版本為1, 客戶端B的當前版本號為2,此時發布版本3的更新,這個時候客戶端A和客戶端B的更新列表是存在差異的,該如何處理?在單文件更新方案下,這不存在問題,A和B都是以3的版本文件,在客戶端本地直接生成差異列表,去下載對應的文件即可。但是在差異包更新方案中,就需要生成如1-3,2-3這樣的版本差異包。而且游戲客戶端的更新是比較頻繁的,就表示每次更新,所需要的差異包是非常多的,因此考慮到不必要的工作復雜度提升,需要提出一個基准包的概念。每次進行了底包(玩家重新安裝了客戶端)更新,底包對應的資源版本就是一個基准的,無論玩家多久不更新,他都有一個基准的包,因此生成差異包的時候,可以針對這個基准包生成一份差異包,這樣就能保證功能的正常更新了。因此我們的差異包就包含了:版本間的差異包,與基准版本的基准差異包。

  我們控制一個版本跨度,比如5,設定一個基准版本0,假如客戶端A的版本號是6,資源服務器的版本號是7,版本跨度是1,在我們設定的跨度之間,客戶端A更新的時候就下載6-7之間的差異包;客戶端B的版本號是5,與資源服務器的版本跨度是2,下載5-7的包;客戶端C的版本號是1,與資源服務器的版本跨度是6,大於我們設定的限值了,這個時候就下載0-7的基准差異包。 這樣就能保證不同版本的客戶端,也能下載到統一的更新資源。

  解決了上述問題,我們實現的差異包更新方案,在實際的體驗中,就是一個字:快!在帶寬一致的情況下,大概算了一下,之前需要10s才能完成的更新,現在只要1s不到的時間就能下載好,再根據設備配置的差異存在一定的解壓時間,但是總時間是小於之前那個方案的。這個方案不涉及到引擎相關(最多就是用引擎的接口拿獲取文件大小),因此可以加入到使用到了熱更新方案的不同開發項目中去。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM