テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】AssetBundleでSpriteAtlasを使用する際に知らないと起こすかもしれないトラブルと、その回避方法

f:id:tsubaki_t1:20181224015603j:plain
Sprite Atlasの設定

幾つかのページ*1*2にて、Sprite AtlasとAssetBundleの組み合わせで問題が起きるという話を聞いたので、確認してみました。

SpriteAtlasをAssetBundleに格納しただけだと問題が起こる

「よぅし、SpriteAtlasでUIのスプライトをまとめちゃうゾ!」

この問題を起こすシナリオは、こんな感じ。

  1. Spriteを参照するUIを作って、AssetBundleに登録
  2. バッチングの為にSpriteをSprite Atlasに登録(&パック)
  3. Sprite Atlasは複数のAssetBundleから参照できるように独立したAssetBundleに格納

f:id:tsubaki_t1:20181224175125j:plain
Prefabが参照するSpriteをSpriteAtlasに登録しただけだと問題が起こる

これをしても、UIを格納したAssetBundleとSpriteAtlasを格納したAssetBundleで依存関係は生成されず、全てのAssetBundleがパックしたTextureを持つ事になります。またAssetBundle毎に違うTextureを使っているので、全体としてみればバッチングは殆ど効いていません。

「良かれと思ってやったが、まさかこんな結果になるとは…」

手っ取り早い解決策:SpriteAtlasに登録したSpriteもAssetBundleに格納

Sprite AtlasとSpriteを生成するTextureを同じAssetBundleに格納することで問題を回避出来ます。
SpriteAtlasが参照するSpriteを持つTextureのBundleがAtlasになっていればOKです。

f:id:tsubaki_t1:20181224175224j:plain
SpriteAtlasとSpriteを同じAssetBundleに登録、それを他AssetBundleから参照する

Spriteを参照している場合はAtlas Textureと元々のTextureの双方の画像データが含まれる事は無いです。元々のTextureの画像データは含まれません(条件有)

f:id:tsubaki_t1:20181224015626j:plain
Sprite Atlasが参照するSpriteが同じAssetBundleに含まれていればOK

何故そうなるのか?

多くの人が勘違いしている項目ですが、AssetBundleの依存関係は指定のアセットを参照しているAssetBundleから、指定のアセットを直接保持しているAssetBundle へ行われます。

例えば下の図では、AssetBundle Aが持つMaterialをAssetBundle Bが参照することが可能です。これはAssetBundle AがMaterialを直接保持しているためです。一方、AssetBundle Aが持つMaterialが参照しているTextureを、AssetBundle Cが参照することは出来ません。これはTextureはmaterialの参照に寄って暗黙的に含まれるアセットの為です。

もしAssetBundle CがAssetBundle のTextureを使用したい場合は、AssetBundle AはTextureにAssetBundle Nameを設定する必要があります。

f:id:tsubaki_t1:20181224030957j:plain

これを今回のケースに当てはめて考えてみます。

Prefabが参照しているのはあくまで「Sprite」であり、Spriteの先の何某かを見ていません。またSpriteAtlasもSpriteを見ていますしTextureをパックしていますが、Spriteを直接保持していません。

つまり上の「AssetBundle AとAssetBundle Cの関係」と同様で、PrefabとSpriteAtlasどちらも暗黙的に参照しているだけです。これではPrefabからSpriteAtlasへの依存関係は構築出来ません。

f:id:tsubaki_t1:20181224045335j:plain
Bundleがautoのテクスチャが含まれていると問題が発生する

なのでSpriteAtlasと同じAssetBundleにはSpriteを配置し、Prefabを格納したAssetBundleはSpriteを参照する形に切り替えます。これなら他のAssetBundleからSpriteAtlasを格納したAssetBundleのSprite(パックしたテクスチャ使用)を使えます。

Sprite生成元の画像データでAssetBundleのサイズが膨らむ事は無い(条件有)

ここで気になるのが、データの重複です。つまりSpriteAtlasでパックしたTextureとAssetBundleに含めた(Spriteを作った)Textureでデータサイズが増えないのか? という話です。

結論を言えば、Textureの持つ画像データは、普通に使っていれば増えませんでした

普通に使っている…つまりSpriteを経由してテクスチャにアクセスしてるだけの場合はデータサイズは増えません。AssetBundleに格納したTextureのデータは破棄され、Textureを取得してもNullを返されます。またSpriteは常にパックしたTextureを使用します。

f:id:tsubaki_t1:20181224043514j:plain
Textureを取得しようとしてもNull

一方普通ではない使い方…つまりSpriteを使いつつもTextureとしても使っている場合はデータサイズは増えます。例えばRawImageのPrefabで参照していたり、MaterialのMainTextureとかで参照している場合もそうでしょう。その場合はSpriteAtlasでパックした画像と、パック前の両方が含まれます
まぁMaterialで使いたいのはパック前の画像でしょうから、これは期待通りの動作と言えます。

f:id:tsubaki_t1:20181224181403j:plain
MaterialからTextureを参照する(パック後ではなくパック前のTextureが必要と判断される)

f:id:tsubaki_t1:20181224182030j:plain
左上:Spriteのみ参照 右下:Textureも参照(Materialで)

Spriteの情報が重複するんじゃないの?

たぶんその通り。
今回のアプローチは、SpriteAtlasが保持するSpriteとTextureが持つSpriteは多分重複します*3。まぁInclude in Buildの方はSprite情報が全ての参照元に残るのでコレの比ではないのですが。

で、この回避方法は簡単、SpriteAtlasをAssetBundleに含めない事です。

f:id:tsubaki_t1:20181225125419j:plain
SpriteAtlasをAssetBundleに含めなくても良い

そもそもSpriteAtlasはSpriteが参照するTextureやUVを差し替える機能です。そしてSpriteAtlasによるSprite情報の差し替えはビルドのタイミングで行われる為、別にAssetBundleにSpriteAtlasアセットを含めなくてもパックしたTextureを使用します
(なお、これは逆を言えば、Spriteを複数のAssetBundleにバラバラに配置すると、全てのAssetBundleにパックしたテクスチャが含まれるという事を意味します 。つまりSpriteAtlasで使用したSpriteは一つのAssetBundleに統合して格納するべきです)

f:id:tsubaki_t1:20181224200847j:plain
SpriteAtlasがAssetBundleに無くとも、Spriteははパックされたテクスチャを使用する

逆に、Sprite参照して使ってない場合…例えば殆どのUIはスプライトをソースコードでセットするようになっている場合は、Spriteを含める必要はありません。その場合はSpriteAtlasを入れてGetSpriteでスプライトを取得するのが手っ取り早いです。AssetBundleに明示的に含めるアセットは減らすべきなので、本当にほとんど動的に取得してるなら、コチラのほうが理にかなっています。

f:id:tsubaki_t1:20181225125743j:plain
GetSpriteでスプライトを取得する

どのアプローチで取得した場合も、テクスチャはパックしたTextureを使用します。

結局、どのように使えばよいのか

もしSpriteを他のPrefabから参照している…そういった設計を行いたい場合、SpriteAtlasでパックした後、パック対象のSpriteを単一のAssetBundleに格納します。これでSpriteAtlasがパックしたテクスチャを使用したSpriteを、他のAssetBundleが使用できます*4

逆に、特に殆どSpriteを動的にセットするといった場合は、Sprite AtlasのみをAssetBundleに格納し、GetSpriteでSpriteを取り出すというアプローチが良さそうです。AssetBundleに明示的に含めるアセットは出来る限り減らすべきです。

単一のAssetBundleでしかSpriteAtlasでまとめたスプライトを使用しない場合は、上2つのような面倒なことはしなくても良いです。SpriteはAssetBundleに格納しなくても良いですし、Prefabで参照する形でしかアクセスしないならSpriteAtlasも不要です。

まぁ、所詮スプライト…無圧縮で数KB程度の細かいデータなので、SpriteAtlasを入れるか入れないかで迷うよりは、普通にSpriteAtlasとSpriteAtlasが参照するスプライトを全部突っ込むという方が楽で良いよねという印象です。とにかくパックしたテクスチャが重複しなければ問題無いので、変に色々と考えるよりもSpriteとSpriteAtlasを一つのAssetBundleにまとめるという上で書いた「手っ取り早い解決策」を使った方が良いかなという
(本当に必要なら状況で使い分けは必要だろうけど)

補足

SpriteRendererは「Sprite Default」マテリアルを使ってるとアセットが重複する(=バッチが途切れる)ので、注意が必要です。
UIだと(MaterialがNullで、実行時に参照するので)コレは起こりません。

感想

ネタバレすれば非常に単純なルールなのですが、コレを知らないと凄いメモリやロード時間、コードサイズや工数のロスに繋がりそうな感じがします。

関連

本質的に似てる問題

tsubakit1.hateblo.jp

依存関係のルールが気に入らない? カスタムしようぜ!お前実装な!

tsubakit1.hateblo.jp

今回と同じ、知らないとエグい事になる系

tsubakit1.hateblo.jp

*1:unityでのatlas texture2018最新状況 - Qiita

*2:Spriteをパックする新しい仕組み、SpriteAtlasを使ってみた【Unity】 - (:3[kanのメモ帳]

*3:Instance IDでしか確認してないので、実際にそうなのかは把握出来てない

*4:1Asset1AssetBundle?今回それをすると死ぬぞ

【Unity】Cinemachineで撮影の構図を色々して良い感じにしたい

この記事はUnity #2 Advent Calendar 2018の20日目の記事です。今は21日だって!?それは本当かい!?まさか遅刻したのに間に合った事にしたのかい!?

qiita.com

前回はがむ (@gam0022) | Twitterさんの[Unity] カスタムシェーダーでTextMeshProに独創的な演出を加えるという超エモい記事でした。

自分のターンではCinemachineを使用して、カットシーンや動画撮影でよくあるような構図について色々と書いてみます。

動画の構図

動画撮影について勉強すると、よく出てくるのが「構図」という話です。ショットを決める上で、画面の何処に何を置くか…という話は基礎的な話で、多くの映画はこの構図をある程度意識して作られているみたいです。実際、映画を構図を意識してみると、確かに意識していそうな配置の事が多いです。

構図には黄金のルールがある

ルールは結構色々なものがあります。

一番有名なのは、三分割法(rule of thirds)です。これは非常に多くの動画や写真のチュートリアルとしても紹介されており、デザインの基礎として扱われている物です。これはゴールデンルールとすら言える物で、本当に多くのデザイン系資料の基本とされています。

等間隔に引いた水平線と垂直線2本ずつにより画面を9等分(上下・左右方向にそれぞれ3等分)すると仮定し、それらの線上、もしくは線同士の交点上に構図上の重要な要素を配置すると、バランスが取れて安定した構図が得られるというものである

f:id:tsubaki_t1:20181220222806j:plain
Unite 2016 : ホンモノ志向のVR空間づくり より

インスピレーションという点では、下のムービーは自分のお気に入りです。

vimeo.com

また左右対称(symmetry)も有名です。特に奥行きを表現する上で、よく見る構図です。

他にも色々と法則はあります。例えば対象をハイアングルで撮るかローアングルで撮るか。画面内の物をバラバラに置くかバランス良く置くか。奥行きをどう表現するか、もしくは表現を意図的に潰すか。180度の原則や被写界深度で何処まで表現するか。

f:id:tsubaki_t1:20181220225158j:plain
ローアングルとハイアングルで印象が若干変わる

勿論、常に同じ構図で作るのは退屈なのでルールを破る事は推奨される事でしょうが、それは「ルールを把握した上であえて破る」という話です。料理の基礎も出来てないのにオリジナルレシピを作っても大して美味しくないように、偉大なるルールがあるならば、それに乗るのは良い事でしょう。

何にせよ、問題なのは「何処に何を表示するのか」という話です。特に焦点を当てるキャラクターを何処に置いて、その上でどのように表示するのか。そういったものをCinemachineで色々とやってみました。

CinemacineはカメラのIK

先日、SIGGRAPHにてCinemachineはカメラのIKという言葉を聞き「なるほどな」となりました。

カメラは多くの場合取りたい構図を考えたら、良い感じの位置を探して、被写体の位置に合わせてカメラの向きやレンズの種類を切替えて良い感じの構図を作成します。それに対してCinemachineでは、撮影したい被写体の位置と大きさをまず決めて、その後にカメラの位置を決めます。被写体の位置のまま、意味のあるカメラアングルを後で探す事が出来るのは、割と面白いです。

例えば普通のカメラの場合、多くの場合で便利なのはSceneViewでカメラを動かし、良い感じの位置を見つけたらショットを取るというアプローチでしょう。

f:id:tsubaki_t1:20181220230610g:plain
カメラを普通に移動した場合

Cinemachineの場合、対象を良い感じの位置に配置して、その後にカメラの位置を調整します。下の画面では左上の半分はキャラクターで覆う事を事前に確定しておき、その上でカメラの良い感じの構図を探します。

f:id:tsubaki_t1:20181220230907g:plain
Cinemachineで構図のセットアップ

Cinemachineで構図を作る

さっそくCinemachineで構図の云々をやってみます。

対象を画面の何処に置くのか決める

まずCinemachineLook Atで、フォーカスを当てる対象を決めます。これで対象を追跡するようになるので、あとは青い線の中心をドラッグ&ドロップして、フォーカスする対象を画面の何処に配置するのかを決めます。

f:id:tsubaki_t1:20181220231339j:plain

フォーカスすべきキャラクターが何処に表示されるのか決まっているなら、カメラはかなり自由に色々な位置に動かせます。例えば映画でよくある肩なめショット(OTS)は、とりあえずキャラクターの後ろにカメラを移動すれば良いので非常に楽に実現出来ます。

f:id:tsubaki_t1:20181221000135p:plain
手前にキャラを置くことで距離感を出す

FOVを変えての調整も楽なので、かなり楽しいです。大きすぎるとゆがみますが、距離感が出て勢いが出ます。

f:id:tsubaki_t1:20181221103210j:plain
キャラクターは同じ配置だがFOVが大きく違う場合。広いと勢いが出る

三分割法を使って、何処に置くか決める

画面の何処に配置するのかを決めるのに便利なのは、上で紹介しているような三分割法のルールです。これは単純に画面を三分割した画像を用意して、Cinemachine.Storyboadにセットするだけです。ホットスポット(線の交差点)に目や顔といった力のある物を置いておくだけで良いので、楽です。

この時、AspectStreatch To Fitに指定しておくと、画面比率によらず三分割してくれて楽です。

また、場合によっては、絵コンテ的な物を貼り付けるのでも良いです(本来はそういう使い方)。同じような構図の絵コンテを作成し、同じような構図の絵を何度も流す事で、以前のショットとの対比を出す等も面白そうです。

f:id:tsubaki_t1:20181220231638j:plain
画面を三分割するように線を引く

画面のどれぐらいの割合で表示するか決める

大きさも決まっているなら、Cinemachine.Follow Zoomを使用します。これは被写体をどのくらいの大きさまで表示するかという物ですが、逆を言えば常に同じ大きさで表示されます。

f:id:tsubaki_t1:20181221101431g:plain
距離を変えても、画面の占める面積は変わらない

ただしFOVを変化させているので、絵が変形したり背景が変化する点には注意が必要です。 例えば下の2枚は、FollowZoomを使用してカメラの距離を変更しているものです。若干キャラクターの幅が変わった他、背景の表示量が変化しています。特にクローズショット(近くで撮影)の場合は画角を広く撮る事が一般的だと思いますが、それはアニメ調の表現と相性が悪いので注意が必要です。

f:id:tsubaki_t1:20181220235446j:plain
左:画角広い 右:画角狭い

被写界深度でフォーカスする

同時に、Cinemachine.Post Processing被写界深度の深さも調整します。浅くすれば誰にフォーカスがあたっているのか分かりやすくなります。Focus Tracks Targetにチェックを入れると、Look Atで指定した対象にフォーカスが当たります。

被写界深度の設定は、CM vcam1 Profileの差し替えで行います。Cinemachineを使用している場合、Virtual Camera毎にプロファイルが設定出来るので、ショット毎に被写界深度を浅くしたり色々出来ます。

f:id:tsubaki_t1:20181221002026j:plain
浅い、深い

Cinemachineが追跡せず、構図だけを使いたい

さて、Cinemachineで構図を作る訳ですが、それを望まないケースも多々あります。例えば、キャラクターが画面外から入ってきて…という場合。この場合、キャラクターを常に追跡するのは望ましくありません。

個人的な結論は、構図の段階では追跡するが、構図が確定したら動かさないというものです。これは単純にCinemachineCompositreNoneにすれば実現します。

f:id:tsubaki_t1:20181220234313j:plain
AImをDo Nothingに設定

場合によってはTimelineで他のカット(カメラワーク)とのブレンドを行う事で、通常は対象を追跡しつつ、重要な瞬間は構図通りの位置に到達する…という事が出来ます。

ただしDo NothingにするとComposeの設定が全て飛ぶので、そこんとこ注意です。

感想

トライアンドエラーで色々と調整出来るので、結構面白いです。 オレはようやくのぼりはじめたばかりだからな このはてしなく遠い構図坂をよ

次はGREAT__SHARK - Qiitaさんが「ECS初心者の導入レポートのようなもの」を書いてくれる予定です。

関連

【Unity】Cinemachineで作るカメラワーク(カット割り:カメラを切り替える) - テラシュールブログ

【Unity】Cinemachineでカメラに映る被写体のサイズをコントロールする - テラシュールブログ

【Unity】Cinemachineでカメラに映る被写体のサイズをコントロールする - テラシュールブログ

【Unity】PostProcessingStackの被写界深度のピントを動的に変更する - テラシュールブログ

【Unity】「被写体のどこを映して欲しいか」を元にカメラの動きをコントロールするCinemachine BASE RIG を軽く使ってみる - テラシュールブログ

【Unity】Photoshopで作った画像をレイヤー単位で分割、配置/描画順をそのままにSprite Renderで配置してくれる 「2D PSD Importer」

今回はPSDのスプライトをレイヤー単位でスライスし、Photoshopの配置そのままにインポートするPSD Importerという機能を紹介します。

PSD Importer

PSD Importerは、PSBをインポートするカスタムインポーターを提供するパッケージです。PackageManagerで管理されています。

このパッケージをPSBをインポートすると、レイヤー単位でスプライトをスライスして別途パッキング、元のレイアウトを元にPrefabを(位置やレイヤーの順番そのままで)生成までしてくれます。

特に2D Animationや2D IKパッケージと連携すれば、複数のスプライト構成したままキャラクターリグまで作り込む事が可能になりそうです。

なおPSD Importerという名前ですが、使えるフォーマットはPSBです

f:id:tsubaki_t1:20181218194453g:plain
レイアウトした状態でリグを調整する図

f:id:tsubaki_t1:20181218192323j:plain
PSBファイルの様子

f:id:tsubaki_t1:20181218192339j:plain
ドラッグ&ドロップでインポート

f:id:tsubaki_t1:20181218192401j:plain
自動的にスライスされる

f:id:tsubaki_t1:20181218192420j:plain
レイアウト済Prefabになるので、そのまま使える

現状UIには使えません。スライスする所までは使えますが、レイアウトは自分で行う必要があります。現状、PSDから直接UIを作成するという目的ならば、 GitHub - kyubuns/Baum2: Psd to Unity UI(uGUI) を始めとしたライブラリの方が有益そうに見えます。(殆どの需要ってソッチだよねって気もしなくも)

qiita.com

PSD Importerの導入

Pacakge Managerから導入します。

f:id:tsubaki_t1:20181218193044j:plain
PSD Importer in PackageManager

後はPSBをインポートすれば、自動的にスライスしてくれます。

なおアンカーの位置は基本的に中央なので、2D Animationや2D Packageを使わないなら調整する必要があります。

PSD Importerの設定

PSBをインポートすると、幾つか新しいオプションが追加されます。b

名前 機能
Import Hidden hidden layersをインポートします
Mosaic レイヤー単位でスライスします
Character Rig スプライトをPSBと同じ位置に再配置します
Use Folder Grouping PSBと同じオブジェクト構成で作ります
Pivot キャラクターの中心位置を調整します

f:id:tsubaki_t1:20181218193312j:plain
インポートしたPSDの設定項目

他にも幾つか設定はありますが、マニュアルをどうぞ。

感想

以前2D Animationで色々やるときに、バラバラのスプライトを渡されて凄い頑張って位置や描画順を調整した覚えがあるので、その辺りが一発で出来るのは割と有り難いです。

ik設定して動かす編に続く…

tsubakit1.hateblo.jp

関連

分かりやすい手順紹介動画(英語)

www.youtube.com

PSBが欲しい人向けのサンプルプロジェクト

github.com

【Unity】iOS/Androidでアプリを休止してもダウンロードを続ける BackgroundDownload

今回はタイトルの通り「アプリを終了(もしくはサスペンド)してもダウンロードを継続する」機能を提供するアセットの機能と使い方についてです。

このアプローチを導入すると、アプリ開始時の「追加コンテンツダウンロード待ち」でアプリを起動しっぱなしで待たずとも良くなります

アプリのバックグラウンドでダウンロード

通常のWebRequest系は非同期で動作しますが、基本的にダウンロード処理はアプリが動作していないと動きません。このため、多くの場合ダウンロード中に色々と工夫が加えられています(漫画を表示とか、ミニゲームとか)

今回のアプローチでは、アプリを休止もしくは停止した状態でもダウンロードを継続してくれます。つまり、このダウンロード時間を他の操作(例えばTwitterを見るとか!)に使うことが出来ます。

単純に消費電力の低下にも良いかもしれません。

電池消費のそれなりの割合はGPUと通信(4G)です。Unityは毎フレームGPUを動かすゲームエンジンなので、ゲーム画面でダウンロード待ち処理を行うと、GPUと通信でバッテリー消費量が増大しますし、端末も熱くなります。逆にGPUを止める(フレームレートを超落とす、CameraとCanvasを全て止める)と、Energy ImpactLowに下がります。*1

さらにアプリをバックグラウンドに持っていけば、メインスレッド/ワーカースレッドも、GPUも動いていない状態になるので、もっと消費電力を下げる事が期待出来ます。

f:id:tsubaki_t1:20181216131027p:plain
レンダリングを止めてGPUを抑えた時の消費電力

BackgroundDownloadの概要

github.com

BackgroundDownloadiOS/Android/Windows Platform向けプラグインです。このプラグインはアプリのバックグラウンド*2でファイルのダウンロードを可能にします。

ダウンロードしたファイルはApplication.persistentDataPath以下に保存されます。BackgroundDownloadにはダウンロードしたbytesにアクセスするインターフェースが無いので、System.IO系のAPIダウンロードしたファイルへアクセスする流れになります。

f:id:tsubaki_t1:20181217002109j:plain
ダウンロードと利用は完全に分かれている

BackgroundDownloadWindowsMac、というよりUnity Editorで動作しません。
エディター上で動作をテストする場合は、BackgroundDownloadがダウンロードしたファイルを保存するフォルダに、ダウンロードすべきファイルを置いて*3動作確認をする流れになるんじゃないかなと思います。

導入

  1. GitHub - Unity-Technologies/BackgroundDownload: Plugins for mobile platforms to enable file downloads in backgroundBackgroundDownloadフォルダとPluginsフォルダをUnityプロジェクトに入れます。

iOSなら、コレで解決します。

Androidの場合、Manifestを少し弄る必要があります。

  1. Manifestを用意
  2. <receiver android:name="com.unity3d.backgrounddownload.CompletionReceiver"></receiver><application>の中に追記
  3. <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />を追加

要するに、下の項目を自身のManifestへ移植します。特にjava.lang.SecurityExceptionが出た場合、マニフェストが正常に設定されていません。

f:id:tsubaki_t1:20181217002559j:plain
自身のManifestファイルに移植すべき項目

使い方

後は使うだけです。

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が可能です。

gist.github.com

ダウンロード完了時や、ダウンロード進行度を通知で出したい

現状、プラグイン自体を書き換える必要があります。

f:id:tsubaki_t1:20181217003856j:plain
Androidの通知にダウンロード進捗を表示

補足

  • Q : iOS でバックグランドのダウンロードは5分かそこらでOSから強制的に落とされる?
    A:backgroundTaskではなくNSURLSessionDownloadTaskを使用しているので、多分そういうことは起こらない
  • Q:沢山のファイルをダウンロードしようとすると、セッションの限界に到達しない?
    A:ダウンロード処理は最大4つ並列で処理され、他はキューィングされる。

感想

毎回長時間のダウンロードを待たされる身としては非常に良い機能に見えますが、コレ自体はかなり昔から実現可能なアプローチであり、その上でコレを利用していないゲームが過半数を占めるということは、何か問題があるのかもしれません。(例えばバックグラウンドにした後にプレイヤーが帰ってこない等のサービス的な問題とか、技術的な要因とか)

何にせよ簡単に出来るようになったのは有り難い。

*1:通常はHih ~ Very Highの間ぐらい

*2:アプリの裏側という意味、別スレッドという意味ではない

*3:ダウンロードに成功したという扱い

*4:iOS以外