我居然踩了兩次,很重要所以我貼在這裡 如果你的專案obb輔助那麼你可能會遇到跟我一樣的問題!
情境說明
Vuforia 是一套可用來開發 AR 擴增實境應用的 SDK,並且內建在 Unity 2017.2 之後的版本,算是易取得、易使用的開發工具。此次的專案是以 Unity + Vuforia 開發 AR 應用,但考量到使用者可能是在山區使用,因此規劃將所有需要的 3D 模型都直接封裝在 APK 裡面,造成 APK 超過 100MB。一旦 APK 超過 100MB,就必須拆成 APK 與 OBB(APK 擴充程式檔)。
當使用者從 Google Play 下載應用程式時,會同時下載 APK 與 OBB 檔,所以對終端使用者而言,操作上並沒有太大的差異。對以 Unity 做為遊戲開發工具的開發者而言,由於 Unity 內建支援將 APK 拆分封裝的功能,開發者只要在發佈前勾選「Split Application Binary」,Unity 會將主要的程式封裝成 APK,而把相關需要的資源(例如貼圖、模型、影片等)存成 OBB,所以這算是遊戲開發領域常用的技巧。
然而,此法運用在以 Vuforia 開發的應用程式上,會發生一個嚴重的問題。Vuforia 之所以可以辨識圖騰而顯示出對應的數位內容,主要是透過 Vuforia 平台提供的 .dat(database)及 .xml 檔,當使用 Unity 封裝應用程式後,這兩個檔案預設會放在應用程式下的 StreamingAssets 資料夾裡,在這資料夾的任何檔案都會被如實地複製到對象載具(設備)的一個特定資料夾,且不會針對這資料夾的內容進行壓縮或加密,具體可參考「Unity资源路径及加载外部资源介绍」一文。
新增一個空的腳本程式(script),並命名為「ObbExtractor.cs」,然後貼上下列的程式碼建立一個新的場景(scene),在新的場景裡放入空的 GameObject,並套用 ObbExtractor 程式元件把這個場景加到封裝列表裡,而且順序必須比 Vuforia 的場景前面
using System.IO;
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class ObbExtractor : MonoBehaviour {
void Start () {
StartCoroutine(ExtractObbDatasets());
}
private IEnumerator ExtractObbDatasets () {
string[] filesInOBB = {"VuforiaMars_Images.dat", "VuforiaMars_Images.xml"};
foreach (var filename in filesInOBB) {
string uri = Application.streamingAssetsPath + "/Vuforia/" + filename;
string outputFilePath = Application.persistentDataPath + "/Vuforia/" + filename;
if(!Directory.Exists(Path.GetDirectoryName(outputFilePath)))
Directory.CreateDirectory(Path.GetDirectoryName(outputFilePath));
var www = new WWW(uri);
yield return www;
Save(www, outputFilePath);
yield return new WaitForEndOfFrame();
}
// When done extracting the datasets, Start Vuforia AR scene
SceneManager.LoadScene( "0-Splash" );
}
private void Save(WWW www, string outputPath) {
File.WriteAllBytes( outputPath, www.bytes );
// Verify that the File has been actually stored
if( File.Exists( outputPath ) )
{
Debug.Log( "File successfully saved at: " + outputPath );
}
else
{
Debug.Log( "Failure!! - File does not exist at: " + outputPath );
}
}
}
前述的作法中,關鍵是在實際執行 Vuforia 前,透過上述程式碼先從 OBB 檔中找出 .dat/.xml 等檔案並複製到 StreamingAssets 資料夾裡,這樣一來,當進入 AR 應用的場景並載入 Vuforia 元件時,就不會因為載不到所需的檔案而無法順利初始化 Vuforia 元件。
進階應用
在前述作法中,是將初始場景設計為空白的,當載入 Vuforia 資料庫後,就會直接跳轉到 AR 相機的場景;而在我的案例中,則是設計了一個初始選單的場景,同時在執行這場景時先預載 Vuforia 資料庫,這樣的設計其實可以提供較佳的使用者經驗。
其次是,如果想要將這段程式碼同時應用在 Android / iOS 的環境下,而不需要管理兩套程式碼,那麼可以針對 Start() 函式裡的程式碼做小幅度的修改,例如
if( Application.platform == RuntimePlatform.Android )
StartCoroutine( ExtractObbDatasets() );
else
StartCoroutine( LoadMainMenuAsync() );
Comentarios