開發了半年基於Unity的安卓應用,項目也基本快完結了。在開發過程中遇到了很多坑,然而Unity的技術支持幾乎都在英文論壇裏。直接百度,真的很難解決問題。本篇對這半年的開發經歷做一個總結,希望能幫助其他開發者。
https://forum.unity.com/ 這個是Unity的官方論壇,個人認爲解決技術問題很好的途徑,就是回覆不是很穩定,看情況,然後網絡訪問也不是很穩定。下面就從我在上面的提問開始寫:
1. Gradle build failed
原帖地址:https://forum.unity.com/threads/gradle-build-failed.647581/#post-4910888
錯誤信息爲:
stderr[
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring root project 'gradleOut'.
> Failed to find Build Tools revision 29.0.0
這個錯誤信息其實就是Unity選擇了一個不存在的安卓BuildToolsVersion版本。這個問題的出現是由於兩個原因:
a. 出現問題之前我PC上一直都用的Android 28,在Player settings裏面目標API Level也是Android 9(28)。但是突然某天Android Studio給我下載了"29.0.0-rc1"這個測試版本的SDK(Unity使用的是Android Studio下載的SDK)。從此,Unity在Gradle Build的時候,並沒有按照我設置裏面的API Level 去直接選擇Android 28這個版本,而是選擇了29.0.0-rc1這個最新版本的BuildToolsVersion。這個可能是由於BuildToolsVersion總是選擇最新的。
b. Unity即便選擇了這個29.0.0-rc1 BuildToolsVersion版本,但是它寫入Gradle文件的時候,卻只寫入了29.0.0. 所以,最終Gradle Build的時候就找不到29.0.0這個BuildToolsVersion版本。
解決方法:
1. 用Unity自己下載SDK, 在Android Studio中導入項目時選擇使用項目中的SDK路徑,即Unity的SDK路徑。
2. 在安卓的SDK目錄下刪除29.0.0-rc1這個版本。
3. 用Unity導出Android Studio項目,然後在Build.gradle裏把 buildToolsVersion '29.0.0'改爲你想用的那個。
2. 在StreamingAssets中加載.XML文件可能會解析錯誤
原帖地址:https://forum.unity.com/threads/how-to-load-a-xml-file-in-android.662320/
首先,StreamingAssets裏面的資源屬於壓縮只能讀取的文件。所以要使用UnityWebRequest的方式來讀取,不能直接去用C#文件流打開。否則在編輯器裏模擬沒問題,但是無法在設備上使用。
解析.XML文件的錯誤是這樣的:在編輯器裏面模擬加載沒問題,在設備上打開也沒問題,讀取的字符串看起來也正常,就是反序列化的時候出現錯誤。
原因是由於.XML文件的BOM造成的。BOM是文件剛開始的一個標記數據,標記字節順序的,佔三個字節:“EF BB BF”。這三個字節後面的纔是反序列化的內容。在安卓上讀取到BOM要跳過,把BOM後面的字符串進行反序列化操作。
解決方法:
1. 生成.XML文件的時候不要帶BOM;
2. 讀取的時候先判斷前三個字節是否爲BOM,如果是就從BOM後面開始反序列化。
3. Unity2018.x升級到Unity2019.1.0.f2時的圖片撕裂問題
如上圖中所示,左右兩個Image使用的是同一個Sprite,但是顯示效果完全不同。我也確認了右邊的Image不存在拉伸或壓縮等行爲,大小和Sprite的分辨率是一樣。感覺這個問題應該只是存在於升級過程中,因爲升級之前完全沒出現過。
解決方法:
把Image用RawImage來替換掉。
4. 觸摸屏導致的點擊事件異常
原帖地址:https://forum.unity.com/threads/i-have-a-tough-problem-with-screen-touch.710951/
現象:由於我們使用的是紅外觸摸框,不知道某種原因用戶在點擊的時候,Unity會同時收到兩個點擊事件。這個在一些資源釋放操作時會產生嚴重的bug。這是一個很隱蔽的問題,而且由不同的代碼帶來的錯誤現象也是不同。
解決方法:
點擊的時候,把函數改爲不響應狀態。延時一段時間(如1ms)後再恢復函數的響應。
5. 加載位於AssetBundle或者Addressables中的Video Clip的注意事項
首先,不論是AssetBundle還是Addressables,Video Clip所在的那個資源包都要選擇未壓縮。否則你大概會收到這個錯誤消息:
AndroidVideoMedia::OpenExtractor could not translate archive:/CAB-5b4cd0a92d354858f98b1392dd686137/CAB-5b4cd0a92d354858f98b1392dd686137.resource to local file. Make sure file exists, is on disk (not in memory) and not compressed.
AndroidVideoMedia: Error opening extractor: -10004
不用懷疑什麼格式問題,就是壓縮造成的問題。
另外,Addressables的機制是從Remote服務器下載AddressableAssets然後保存在本地的Cache裏面,再從本地已下載的Cache文件中把VideoClip加載到程序裏。所以在請求更新包含VideoClip的AddressableAssets的時候,要把Caching.compressionEnabled設置爲false,即不壓縮保存。
但是這會帶來另一個問題:Caching.compressionEnables如果全局都設置爲false,那麼其他的素材佔用的空間一下子也會增加幾倍。目前Unity還不支持在下載Addressables的時候選擇是否要壓縮再Caching。
解決方法:
把VideoClip相關的Assets單獨出來處理,不要和其它的放在一起。比如,統一先把Caching壓縮關閉再去更新VideoClips。更新結束後再把Caching壓縮打開更新別的Assets。Addressables這個系統確實省了很多事,但是目前感覺還不夠成熟。