Unity5.3.2, 5.3.3系でAssetBundleがiCloudに入っちゃう暫定対策[fixed]


概要

5.3.2系のみならず5.3.3系p1でもまだダメ。これだけかどうかはわかんねーけどまとめる。

ただ、検証方法がAppleの作ったGUIごしのものなのでリアルタイム性がすこし怪しく、鵜呑みにせず信じるために疑ってかかってほしい。

→ 5.3.4p1以降で解決された。


症状

iOS用にAssetBundleビルドしてWWW.LoadCacheOrDownload で取得するとなんとデータがiCloudに載る

具体的には、こうなる。

IMG_0816.PNG


親にむかってなんだそのデータは!!!

取得したAssetBundleが見事にiCloudに載っとる。これは死ぬぞ。



何がまずいのか

何がまずいって、これ万が一AppStoreの申請を通過してしまうと、AssetBundleや自前で用意したリソース保持用のフォルダが

ユーザーのiCloudに載ってしまう可能性がある。


AppStoreで審査があるおかげで蹴られて気づいた(人から自分はさらに聞いて調べた)んだが、

万が一すり抜けると、数ギガ単位のリソースをユーザーのiCloudにアップしてしまう。

iCloudにはユーザーのデータが従量課金ベースで載っているのがデフォなので、ミスると評判的にも痛い。っていうか死ねるのでは。



原因と解決法

AssetBundleをDLしたあと、iOSのアプリケーションキャッシュ内に保存する際のフラグ設定をおこなう内部APIがあったんだけど、

その設定値がAssetBundle DL時 のみおかしかった。


該当の処理では、Xcodeでの実機用ビルド時に定義されている以下のファイルの関数を使っている。


Filesystem.mm

extern "C" int UnityUpdateNoBackupFlag(const char* path, int setFlag)

{

int result;

if(setFlag)

{

u_int8_t b = 1;

result = ::setxattr(path, "com.apple.MobileBackup", &b, 1, 0, 0);

}

else

{

result = ::removexattr(path, "com.apple.MobileBackup", 0);

}

return result == 0 ? 1 : 0;

}


で、この関数、AssetBundleの保存以外にもいろいろな所からつかっているみたいなんだけど、

AssetBundleを保存するタイミングのやつだけ、setFlag = 0 (Excludeしない)という感じで来てた。


Unity Japanに問い合わせたところめっちゃ早く返答がもらえて、「現状使用している方法が古いので、最新でこんなのどう?」っていうコードサンプルをもらった。

で、


最終的に、関数を次のように書き換えると救われる。

とりあえずUnityでゲームつくっててiCloudの世話になることは無いので(暴言)

固定値でexclude = YESを叩きつける。


extern "C" int UnityUpdateNoBackupFlag(const char* path, int setFlag)

{

    NSLog(@"path:%s, setFlag:%d", path, setFlag);

    int FIXED_YES_NUM = 1;

    return [[NSURL fileURLWithPath:[NSString stringWithUTF8String:path]] setResourceValue:[NSNumber numberWithBool:FIXED_YES_NUM] forKey:NSURLIsExcludedFromBackupKey error: nil] != NO;

}



一応貼っておくと実行時のログは次のような感じ。

2016-02-19 17:11:39.513 ProductName[595:201891] path:/var/mobile/Containers/Data/Application/7D89FD21-A2D1-42B6-AE4C-F5559366E4B9/Library/UnityCache/Temp/f34e32a1dd7804da1921ba641bbdffb9, setFlag:1


2016-02-19 17:11:39.521 ProductName[595:201773] path:/var/mobile/Containers/Data/Application/7D89FD21-A2D1-42B6-AE4C-F5559366E4B9/Library/UnityCache/Temp/f34e32a1dd7804da1921ba641bbdffb9/__info, setFlag:1


2016-02-19 17:11:39.522 ProductName[595:201773] path:/var/mobile/Containers/Data/Application/7D89FD21-A2D1-42B6-AE4C-F5559366E4B9/Library/UnityCache/Shared/e540cdd1328b2b21e29a95405c301b9313b7c346, setFlag:0


2016-02-19 17:11:39.522 ProductName[595:201773] path:/var/mobile/Containers/Data/Application/7D89FD21-A2D1-42B6-AE4C-F5559366E4B9/Library/UnityCache/Temp/f34e32a1dd7804da1921ba641bbdffb9/__data, setFlag:1


2016-02-19 17:11:39.526 ProductName[595:201865] path:/var/mobile/Containers/Data/Application/7D89FD21-A2D1-42B6-AE4C-F5559366E4B9/Library/UnityCache/Shared/e540cdd1328b2b21e29a95405c301b9313b7c346/__info, setFlag:1


setFlag = 0で来てるのが、AssetBundleの保存。

どっかで値が逆転してるか初期値がおかしいか初期値が入ってないか、な気がする。

Unityへは報告ずみ。



結果

Victory~~~~!!

IMG_0817.PNG



追記

自分でも確認したい人向けに下記を用意した。


再現サンプルリポジトリ

https://github.com/sassembla/ShaderKitchen/tree/assetbundle_debug_sorasu



プロジェクトを、ツールバーの Unidon > Publish Site からビルドできる。


ビルド時に、Assetsフォルダと同じ階層に、UnidonWeb/AssetBundle というフォルダ+アセットバンドルが作成されるようになっている。

実機で動かす際は適当なCDNとかにそれらをアップ、DLするURLを書き換えてみてほしい。


アプリケーション実行時、実行時に自動的に1つのAssetBundleを取得しキャッシュしている。

キャッシュにはWWW.LoacFromCacheOrDownload を使っている。

現在までUnity5.3.2系で確認した結果おかしい感じなので、ほかのバージョンでも動かしたりしてみてほしい。

誰か。



さらに追記

ちなみにAssetBundleだけなのか? っていうとさにあらず、

確証がないが、「LoadFromCacheOrDownload」内で使っている関数を、他のAPIが使用している可能性は調べていない。

つまり


「自前でAssetBundle保存箇所作ったから平気だぜ~」

とか


「そもAssetBundleつかってないから平気~~」

とかは


ありえないかもしれない。


少なくとも自分は自分に影響する範囲のチェックしかしてないので、

レッツ調査。


なんかわかったら教えて。Twitterとかで。



さらにさらに追記

5.3.2p4が来てたんで試してみたけどやっぱまだ増えるわ。次かな、、


さらにさらにさらに追記

強火ですすめの人が5.3.2f1でも起きてることを突き止めてくれました。詰んでます。

http://d.hatena.ne.jp/nakamura001/20160220


ランタイムの問題なんで、つらいな。



さ4追記

5.3.3f1でもダメ

これのパッチかな。


た5追記

エクスカリバー255本に増やそうな。

5.3.3p1でもまだダメ。

changeset見てから「あ、、でももしかして、、、もしかしたら、、」みたいなのがあって触ってたけど無駄っぽいので追うのをやめます。

アイドルを卒業します!



5.3.4p1のfixedに入ってた

やったね! ~完~