今回はタイトルの通り「アプリを終了(もしくはサスペンド)してもダウンロードを継続する」機能を提供するアセットの機能と使い方についてです。
このアプローチを導入すると、アプリ開始時の「追加コンテンツダウンロード待ち」でアプリを起動しっぱなしで待たずとも良くなります。
アプリのバックグラウンドでダウンロード
通常のWebRequest
系は非同期で動作しますが、基本的にダウンロード処理はアプリが動作していないと動きません。このため、多くの場合ダウンロード中に色々と工夫が加えられています(漫画を表示とか、ミニゲームとか)
今回のアプローチでは、アプリを休止もしくは停止した状態でもダウンロードを継続してくれます。つまり、このダウンロード時間を他の操作(例えばTwitterを見るとか!)に使うことが出来ます。
アプリのバックグラウンドでデータをダウンロード出来ると、コンテンツのダウンロード中に他のゲームで遊べるという例 pic.twitter.com/hJcFpTbj5M
— 椿 (@tsubaki_t1) 2018年12月16日
単純に消費電力の低下にも良いかもしれません。
電池消費のそれなりの割合はGPUと通信(4G)です。Unityは毎フレームGPUを動かすゲームエンジンなので、ゲーム画面でダウンロード待ち処理を行うと、GPUと通信でバッテリー消費量が増大しますし、端末も熱くなります。逆にGPUを止める(フレームレートを超落とす、CameraとCanvasを全て止める)と、Energy Impact
はLow
に下がります。*1
さらにアプリをバックグラウンドに持っていけば、メインスレッド/ワーカースレッドも、GPUも動いていない状態になるので、もっと消費電力を下げる事が期待出来ます。
BackgroundDownloadの概要
BackgroundDownload
はiOS/Android/Windows Platform向けプラグインです。このプラグインはアプリのバックグラウンド*2でファイルのダウンロードを可能にします。
ダウンロードしたファイルはApplication.persistentDataPath
以下に保存されます。BackgroundDownload
にはダウンロードしたbytes
にアクセスするインターフェースが無いので、System.IO
系のAPIでダウンロードしたファイルへアクセスする流れになります。
BackgroundDownload
はWindowsやMac、というよりUnity Editorで動作しません。
エディター上で動作をテストする場合は、BackgroundDownload
がダウンロードしたファイルを保存するフォルダに、ダウンロードすべきファイルを置いて*3動作確認をする流れになるんじゃないかなと思います。
導入
- GitHub - Unity-Technologies/BackgroundDownload: Plugins for mobile platforms to enable file downloads in background の
BackgroundDownload
フォルダとPlugins
フォルダをUnityプロジェクトに入れます。
iOSなら、コレで解決します。
Androidの場合、Manifestを少し弄る必要があります。
- Manifestを用意
<receiver android:name="com.unity3d.backgrounddownload.CompletionReceiver">
~</receiver>
を<application>
の中に追記<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
と<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
を追加
要するに、下の項目を自身のManifestへ移植します。特にjava.lang.SecurityException
が出た場合、マニフェストが正常に設定されていません。
使い方
後は使うだけです。
APIは非常に簡単で、BackgroundDownloadConfig
にダウンロードしたいファイルや設定を詰めてBackgroundDownload.Start
を呼ぶだけです。
コルーチンで簡単に観測出来ますが、BackgroundDownload.backgroundDownloads[0]
で他の機構から観測するのも良さそうな感じがします。
BackgroundDownloadConfig config = new BackgroundDownloadConfig { filePath = saveFilePath, url = new Uri(downloadFileURL), policy = BackgroundDownloadPolicy.UnrestrictedOnly }; using (var download = BackgroundDownload.Start(config)) { yield return download; Debug.Log(download.status); }
BackgroundDownloadConfigでは、一応、AddRequestHeader
でヘッダー情報を追加したり、ダウンロードが使用できるネットワークの指定*4が可能です。
ダウンロード完了時や、ダウンロード進行度を通知で出したい
現状、プラグイン自体を書き換える必要があります。
補足
Q
: iOS でバックグランドのダウンロードは5分かそこらでOSから強制的に落とされる?
A
:backgroundTaskではなくNSURLSessionDownloadTaskを使用しているので、多分そういうことは起こらないQ
:沢山のファイルをダウンロードしようとすると、セッションの限界に到達しない?
A
:ダウンロード処理は最大4つ並列で処理され、他はキューィングされる。
https://t.co/9u63zFYcut 大量のファイルをダウンロードした場合でも、ちゃんと4つずつダウンロードするの図 pic.twitter.com/bFSGGkH2Oz
— 椿 (@tsubaki_t1) 2018年12月17日
感想
毎回長時間のダウンロードを待たされる身としては非常に良い機能に見えますが、コレ自体はかなり昔から実現可能なアプローチであり、その上でコレを利用していないゲームが過半数を占めるということは、何か問題があるのかもしれません。(例えばバックグラウンドにした後にプレイヤーが帰ってこない等のサービス的な問題とか、技術的な要因とか)
何にせよ簡単に出来るようになったのは有り難い。