Google Playストアのアプリの容量制限は100MBであるため、100MBを超えるアプリはapkとOBBに分割しないといけない。
Unityにその分割機能があるため、面倒なことだと思っていなかったが、実機で動かすと音が鳴らないことに気づいた。
原因を探ると、ADX2 LEのキューシートが読み込めていないようだったので、その対処を行った。
環境
・macOS Sierra 10.12.2
・Unity 5.5.0f3
・サウンド関係はCRI ADX2 LE使用
・キューシート等はStreamingAssets下に配置
原因の特定経緯
症状は効果音やBGMが一切出ないというものだった。
また、分割しないビルドであれば問題なかった。(iOS版でももちろん問題ない)
はじめ、OBBに分割したことによって、OBBの方が読み込めていないのではと考えたが、OBBが読み込めていないとそもそもタイトルシーンでフリーズしてしまったため(環境によると思うが)、OBBの読み込みはできていると判断した。
adb logcat
でログを見ると、
CRIWARE ERROR[w2015111731] : file existence error occurred // 原文ママではない
というエラーが出ていたため、ADX2LEのキューシート等が読み込めていないと判断した。
対処
ググった結果、似たような事例を見つけた。
Android Split APK-OBB and StreamingAssets
Dataset does not exist error when using Unity 4 Android Splitter
どうやら、Application.streamingAssetsPath
内のファイルをApplication.persistentDataPath
にコピーすれば良さそうな感じがした。
上記サイトを参考に、タイトルシーンのスクリプトに以下のコードを加えた。
void Start(){
StartCoroutine(ExtractObbDatasets()); // データのコピーを行うコルーチン開始
}
private IEnumerator ExtractObbDatasets () { // データのコピーを行う
string[] filesInOBB = {"CueSheet_0.acb","CueSheet_1.acb","HogeHoge.acf"}; // .acbや.acfの指定(StreamingAssets下のファイル)
foreach (var filename in filesInOBB) { // 指定したファイルの文だけ実行
string uri = Application.streamingAssetsPath + "/" + filename; // コピー元のパス
string outputFilePath = Application.persistentDataPath + "/" + filename; // コピー先のパス
if(!Directory.Exists(Path.GetDirectoryName(outputFilePath))){ // ディレクトリが存在しなかったら作成(多分使わない)
Directory.CreateDirectory(Path.GetDirectoryName(outputFilePath));
}
var www = new WWW(uri); // 内部的なコピーだが、wwwを使って擬似ダウンロードみたいなことをする
yield return www;
Save(www, outputFilePath);
yield return new WaitForEndOfFrame();
}
}
private void Save(WWW www, string outputPath) { // データのセーブを行う
File.WriteAllBytes(outputPath, www.bytes); // セーブ
if(File.Exists(outputPath)){ // もしセーブ先に書き込んだデータがあれば
Debug.Log("File successfully saved at: " + outputPath); // 成功
}else{
Debug.Log("Failure!! - File does not exist at: " + outputPath);
}
}
ここでのfilesInOBBには、StreamingAssets下のファイル名を入れる。
ADX2 LEであれば、.acb .awb .acfが対象となるだろう。
また、Assets/Plugins/CriWare内のCriWare.csの一部を次のように変更した。
public static string streamingAssetsPath
{
get {
if (Application.platform == RuntimePlatform.Android) {
if (Application.dataPath.Contains(".obb")) { // obbのとき
return Application.persistentDataPath; // このパスを返すようにする
}else{
return ""; // これがデフォになってるはず
}
} else {
return Application.streamingAssetsPath;
}
}
}
さらっと書いてるが、7時間ぐらい無駄にした。