1. 程式人生 > >Unity自動打包工具

Unity自動打包工具

轉載 https://blog.csdn.net/ynnmnm/article/details/36774715

 

最開始有寫打包工具的想法,是因為看到《啪啪三國》王偉峰分享的一張圖,他們有一個專門的“工具程式設計師”開發各種工具。(ps:說起來這個王偉峰和他的創始團隊成員,以前跟我是同一個公司的,公司名字就不透露了,只是當時在不同的部門,相互不認識)。正好我們專案也到了後期,該準備接入渠道了。於是,我就著手寫我們的打包工具。約定一下,下文中,平臺是指作業系統平臺,比如iOS、Android、WP8、Metro;渠道是指釋出渠道,比如App Store、WP8商店、360、91、小米等。

                           

 

                                                         上海火溶網路CEO王偉峰分享的《啪啪三國》打包工具

  過程

    從過程上,主要分為以下幾步:

    1. 資源準備;

    2. 由Unity生成工程;

    3. 生成安裝包;

    4. 資源恢復。

    具體到平臺和渠道,會有一些細微差異,下面具體說。

  WP8打包

    這個是第一個寫的,因為不涉及渠道,相對來說最簡單。從下午4點,寫到晚上9點多,時間大部分花在處理一些細節上。

    第一步,資源相關的準備。我們是做了動態更新的,所以生成工程之前,要先從Unity裡刪去更新的資源,這樣打出的包更小。ps:其實這一步之前,我們會先打更新包,關於資源打包與更新,我另寫一篇文章介紹。另外,跟各個平臺互動,我們寫了外掛,比如,內嵌web功能,Unity是沒有的,要呼叫系統的api來做。就是這麼一個再普通不過的外掛,讓我花了大量時間處理,因為Unity常常load別的平臺目錄下的外掛。比如,我有一個外掛Platform.dll,按照Unity的官方文件,應該放到“Plugins/平臺/”目錄下,生成WP8工程的時候,Unity應該選擇Plugins/WP8/Platform.dll載入;打android包的時候,應該載入Plugins/Android/Platform.dll。但是遺憾的是,Unity不是這樣,我打WP8的時候,它常常去載入Android目錄下的外掛。這個問題的原因,我一直沒有查到,希望瞭解的朋友不吝賜教。為了解決這個問題,我就在打包的時候,把非當前平臺目錄下的外掛刪除,打好包之後,再恢復。另外,還要刪除上一次打包生成的檔案。

    第二步,生成工程。這個沒什麼好說的,就是Unity的API呼叫,比如,BuildPipeline.BuildPlayer(BuildScenes, BuildPath, BuildTarget.WP8Player, BuildOptions.None);

    第三步,生成安裝包。在生成包之前,要替換一些Unity生成的檔案,比如,MainPage.xaml/.cs,因為我們為了操作內嵌web,做了WP8特性的ApplicationBar;我們配置好的WMAppManifest.xml,友盟統計要求初始化必須在App.xaml.cs中,WP8工程Assets/目錄下的Icon等。然後,根據需要修改工程檔案,比如,我們做了WP8的ApplicationBar,需要在打包工具裡把相關的資源索引新增到工程檔案中。然後,就可以呼叫cmd來生成apk安裝包了。cmd主要是呼叫vs的命令,生成apk,呼叫vs安裝目錄下的devenv.exe,配置一下devenv.exe的引數就可以了。這裡有一個需要注意的地方是,Build選項要選擇Master,而不是Release,Release版本有"profiler support",Master才是釋出用的。

    第四步,資源恢復。包已經打好了,為了接下來打別的平臺或渠道的包,恢復資源。比如,恢復更新的資源、各平臺外掛等。

  Android打包

    Android打包麻煩一些,不是因為渠道多,而是因為有的渠道有一些特殊需求。過程類似,下面主要說不同的地方。

    第一步,資源相關的準備。跟WP8打包不同的是,Android是多渠道,要處理各個渠道的資源。我最開始把所有渠道sdk相關的資源和程式碼,都放到Unity的Plugins/目錄下面,比如Plugins/Android360、Plugins/Android91、Plugins/AndroidXiaoMi等,每次打包的時候,資源準備階段先刪除所有非當前渠道相關的內容,然後把當前渠道的目錄名修改為Plugins/Android,打完包再刪除Plugins/Android,然後呼叫svn update更新所有刪除的內容。寫完之後,打一個包,ok。當時接了11個渠道,然後我點了一下“Build All”,Build過程很慢,因為有大量的散檔案,svn update要幾分鐘,Unity import進來這些資源也要一些時間。而且,當打到第四、第五個包的時候,Unity import資源的時候,常常會報錯,可能是因為磁碟上的檔案與Unity的快取檔案之間同步的時候異常。這樣打包太慢了,也無法做到一鍵打幾十個包。後來,我想到把所有渠道檔案放到Unity Assets目錄外,這樣,需要哪個sdk就copy進來哪個,打完包delete就可以了,不用svn update,也不需要Unity每次import大量的散檔案。打包效率提高了幾倍,而且,一鍵出十幾個包,也沒有遇到過Unity報錯。

    第二步,生成工程。這個地方,我是走了一些彎路的。

    最開始,我沒有生成Android工程,而是直接Build出來apk,這樣的好處是快。根據測試,3分鐘多可以生成一個,而生成工程之後再Build出apk,時間翻了一倍。但是,各個渠道的sdk的特殊性,造成這種方式後來出幾次問題。

    第一次,接sdk的同學說,有的渠道要求獨立的icon或splash,我想這個簡單,用aapt直接操作生成apk,修改裡面的內容,然後重新簽名就可以了,非常快,又方便。

    第二次,接百度多酷的同學說,用打包工具生成的apk,充值支付的時候,如果選擇銀聯支付,會crash。而先Build出工程,然後用Eclipse編工程生成的apk沒問題。我仔細對比了兩個apk,發現直接生成的apk裡,比工程生成的apk裡,res/drawable/目錄下少了幾個檔案,data.bin/data_high.bin/data_low.bin/mobilepayplugin.bin,我懷疑是Unity直接生成apk的時候,過濾掉了這些檔案,而生成工程的時候沒有過濾。什麼原因?這個也好解決,找到缺少的檔案,用aapt加進去。後來,當樂、Oppo都需要在打包工具里加入同樣的幾個bin檔案。

    這樣解決,不是好方法,但是解決了問題。但是,後來Oppo的同學反饋說,我們的包開啟的Oppo登入介面是全屏的,而實際應該是彈出視窗樣式。這說明,打包的時候,可能有些介面佈局檔案,沒有打進去。但是,這次,我沒法通過對比兩種方式生成的apk,找缺少哪個檔案了,因為所有的資原始檔,都打到resources.arsc裡面了。這時,我覺得這種出現問題解決問題的思路是不對的,應該從根本上拒絕出問題。然後,我重新寫了Android打包工具,先生成工程,然後用Ant Build出apk。如果哪個渠道有特殊需求,在build apk之前操作工程,比如替換icon、splash。當然,這樣做打包過程變成了,慢了一半。

    第三步,生成安裝包。這個沒什麼好說的,就是Ant、sign、zipalign等。另外,我們的運營有一個特殊的需求,他們投放渠道,分兩種方式:一種是接渠道sdk,另外一種是隻購買流量,不接sdk。針對第二種方式,我打包的時候,只打一個包,然後,為了統計區分投放的渠道,對於生成的這個包,複製一份然後修改包裡的配置檔案,就可以了,不需要重複生成多次包。這樣,十幾秒就可以出一個包。我打包工具裡的“SPP渠道包”這個按鈕,就是是單獨生成這種渠道包的。

    第四步,資源恢復。因為WP8就一個渠道,所以打完WP8包,就要直接恢復所有資源。而Android渠道眾多,為了更快,有些資源是不需要恢復的,比如我們更新的內容。只需要打完所有Android包之後,恢復一次就可以了。

  iOS打包

    寫完WP8和Android打包工具後,我不想再做重複的工作了,就寫了一份詳細的文件,然後交給一個小夥伴,讓他參考WP8和Android的程式碼,寫iOS的打包工具,也是想讓他鍛鍊、學習一下。結果,悲劇無比!!!因為程式碼是很類似的,而且我給他詳細講了怎麼做,iOS也只有3個渠道,他需要寫的程式碼不超過50行,shell指令碼估計在30行以內。這個我本來預估1-2天,最多3天可以做完的工作,他要了一週。而最後,他做了一月有餘%>_<%

    後來,發現有一個第三方工具,XUPorter,可以方便的編輯framework、plist甚至obj-c程式碼,有了它再配合寫點shell指令碼,iOS打包很簡單。

  其它

    我最開始寫工具的時候,打包操作入口用的是[MenuItem(...)],操作按鈕在Unity左上的選單欄,做出來的打包工具操作介面是這樣的:

                     

    我不知道大家有沒有發現有什麼問題。問題就是:每次加渠道,我都要在程式碼裡新增選單項,比如,今天新增91渠道,在程式碼裡新增:


[MenuItem("Build/Build Android Player/91")]
static void BuildAndroid91Player() {
// do something ...
}
    明天添加了360渠道:


[MenuItem("Build/Build Android Player/360")]
static void BuildAndroid360Player() {
// do something ...
}
    如果有幾十個,甚至一兩百個渠道怎麼辦?每次都修改程式碼?NO!ps:我們公司有一款產品真的接了一百多個渠道。

    但是,在函式之外,如何讀配置對C#的屬性[MenuItem(...)]做賦值處理?我還抱著一點僥倖查了一些資料,這是根本不可能的。後來,我想起來之前看到的王偉峰分享那張圖:

                                    

    這張圖雖然很模糊,但是仔細看看,我看出來他們的打包工具操作入口,不是在Unity 頂部的選單欄,而是在Inspector中。瞭解了在哪裡寫,實現就很簡單了,建一個Prefab就可以了。這樣,以後新新增渠道,接入的同學只需要按照我規定的格式,在配置檔案里加一行渠道資訊就可以了。修改後打包工具操作介面:

        

 

                                        我們的打包工具操作入口

    Refresh按鈕是修改渠道配置檔案之後,重新讀取配置檔案。

    Build Patch下面的幾個按鈕是打各平臺的更新包,動態更新用的AssetBundle。

    Build Player下面按鈕式打各平臺、各渠道的安裝包。可以一鍵出某個包,或者一鍵出某平臺的所有包。這裡我沒有做一鍵出所有平臺的包,因為我們沒有這個需求。如果要做,出完一個平臺的包之後,切換一下平臺就可以了(EditorUserBuildSettings.SwitchActiveBuildTarget(xxx))。但是,注意不要Switch之後立即打新平臺的包,而應該在回撥接口裡做,activeBuildTargetChanged。

 

    Unity相關文章:Unity優化總結、Unity3D圖形效能優化、Unity自動打包工具——Mac上打包android

    轉載請註明出處: http://blog.csdn.net/ynnmnm/article/details/36774715。作者:夜風。
---------------------
作者:_夜風_
來源:CSDN
原文:https://blog.csdn.net/ynnmnm/article/details/36774715
版權宣告:本文為博主原創文章,轉載請附上博文連結!