1. 程式人生 > >Android:AS與Unity3D之間打包的各種坑及解決方案

Android:AS與Unity3D之間打包的各種坑及解決方案

近日因為工作的原因筆者開始接觸Unity3D遊戲引擎,該引擎的一大特色就是支援多種平臺,其中自然不能少了我們Android。在Unity3D和Android Studio互動中其實有不少坑,不過踩坑向來是學習的一部分,在這裡筆者和大家分享一下今天的踩坑經驗。

一、 將專案作為lib匯入Unity打包

Eclipse的時代說到打包那必然指的是JAR包,其缺點是res資原始檔不好處理,而隨著Android Studio一同到來的AAR包解決了這個問題。

將原始碼和資原始檔一同打包等到實際編譯的時候再解壓,這些事情Build Tool都幫我們做了,這也是為什麼Android Studio中我們只需一句話就能搞定依賴管理。在Unity3D工程中我們同樣能夠通過AAR來匯入Android部分的邏輯。

博文介紹瞭如何匯出AAR,但是在你真正將自己的專案移植的時候你仍然會遇到不少問題。如果你將自己的AAR包用壓縮軟體開啟時就會發現Build Tool似乎將你整個Module都打包進去,唯獨沒有打包的就是你的依賴!

比如你在Android中使用了ToolBar,RecyclerView等由support-v7提供的控制元件,或者類似xUtils3的第三方框架等,這些東西都是不會被打包進你的AAR中。我們必須手動將這些依賴的AAR一同新增到Unity3D工程。

大部分的第三方庫都會提供AAR包檔案,實在沒有也可以從GitHub上clone下來自己打包。Google官方提供的support庫等都可以在SDK目錄下的extras子目錄中找到,比如support-v7的AAR在如下位置可以找到:


看到這裡你以為就能順利完成往Unity3D匯入Android的工作嗎?

Naive,這裡還有兩個坑你沒跳呢!

如果你的SDK中存在版本為24的Build Tool的話會爆出錯誤:


具體原因可能是Build Tool的Bug。要解決的話很簡單,就是把24的Build Tool藏起來:


到這裡你應該能夠順利地將Unity3D工程順利打包成APK。

這個時候如果你還覺得包的版本越高越好就會遇到第二個坑,這個坑在24號版本的support-v7包中。

報錯截圖如下:


compile ‘com.android.support:appcompat-v7:24.x.x’只是一句依賴但是其匯入的包並不只有一個,如果你開啟module的build\intermediates\exploded-aar目錄去看的話就會發現其實他有4個包。報錯中提到的VectorDrawableCompat就在其中:



然而這個時候就算你匯入了這兩個包問題依舊存在。

筆者猜測24的VectorDrawable包必須使用24的Build Tool來打包,而上面我們說過了24的Build Tool和Unity3D不太相容。

解決方案很簡單,就是使用23的support包。

筆者測試過使用23的support無需匯入VerctorDrawable可以正常執行。

1、 使用Gradle指令碼簡化導包操作

踩過以上的這些坑之後想必大家都已經掌握了新姿勢,但如果你像筆者一樣是個懶惰的程式設計師的話就會覺得,每次編譯都手動複製來複制去好麻煩啊,而通過Gradle的指令碼我們可以分分鐘解決這個問題。

以下是筆者寫的指令碼,當成虛擬碼來看的話相信有點經驗的開發者都能看懂:

// 刪除舊的aar
task deleteOldAar(type: Delete) {
    //刪除Unity工程下的Android資源
    delete '你的Unity3D工程/Assets/Plugins/Android/lib-release.aar'
    //由於AndroidManifest檔案可以能有更新,一併刪除
    delete '你的Unity3D工程/Assets/Plugins/Android/AndroidManifest.xml'
    //刪除Android工程下的編譯資源
    delete 'build/intermediates/bundles/release/'
    delete 'build/outputs/aar/lib-release.aar'
}

// 匯出AndroidManifest.xml
task exportManifest(type: Copy) {
    from('src/main/')
    into('你的Unity3D工程/Assets/Plugins/Android/')
    include('AndroidManifest.xml')
}

//匯出aar
task exportAar(type: Copy) {
    from('build/outputs/aar/')
    into('你的Unity3D工程/Assets/Plugins/Android/')
    include('lib-release.aar')
}

//新增任務依賴
exportAar.dependsOn(deleteOldAar, build, exportManifest)

二、 將Unity作為lib匯入Android Studio

如果你實際將工程作為libs匯出的Unity3D匯出的話你會發現這種方法帶有太多的限制了:

  • 專案所在的Module必須為設為library 
    如果你的專案使用了比如xUtils中的基於註解和反射實現的檢視注入框架的話,你就會發現將module設定為library後框架的檢視注入功能就無法使用了,甚至連switch(view.getId())這樣的程式碼都用不了。究其原因無論是註解還是switch語句其需要引數都必須是常量,而library的R.id.xxx要在打包成apk的時候才能確定,於是開發者就不得不寫繁瑣的findViewById了。

  • 不方便管理依賴庫 
    如果專案依賴了某些庫那麼在打包的時候要一併將這些庫的jar/aar一併匯入到Unity目錄之中,升級依賴或者新增依賴全部都要手動進行。人為操作難免會出問題而Unity打包的速度也是慢的可以,每一次打包都像是在拷問著程式設計師一般。

如果反過來想,不是將工程匯出而是將Unity作為lib匯入到Android Studio的話這一切都將迎刃而解。

開啟Unity的IDE,通過File->Build Settings開啟打包設定 


選中Google Android Project並且簽名(不簽名無法匯出工程,身為Android開發者我表示不解啊),匯出後我們就會看到Eclipse專案結構的工程,如下:

assets存放的是編譯後的Unity指令碼等東西,這部分是匯出部分的核心,日後如果要更新Unity的lib的話,只覆蓋assets下的東西就夠了。其他的部分相信大家都十分熟悉了,不再贅述。

我們將匯出的東西作為library匯入到Android Studio,build之後我們就能在module的輸出目錄下找到對應的AAR檔案了:


之後我們就可以直接使用AAR檔案進行開發了,是不是很方便。

1、 更新Unity的AAR

隨著專案的不斷研發Unity的部分總是需要更新的,如果匯出一個AAR要重複上述的步驟的話那依然是很麻煩的。好在我們可以繞過Android Studio直接更新AAR檔案。

如前文所說Unity匯出工程的核心都在Assets目錄下,而我們用壓縮軟體開啟對應的AAR檔案就會發現Assets下的內容只是被原封不動地打包進去了而已,所以我們完全可以用新匯出的Unity工程中的Assets來替換AAR包下的東西。