Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Haruto Otake
Slide 2
Slide 2 text
● (Unityを対象とした)モバイルゲームのリソース 管理基盤が解決すべき課題と、DeNAが取ったそ れらへの解決策 ● 基盤ライブラリとフレームワークを分離するアプ ローチとその利点
Slide 3
Slide 3 text
● 大竹 悠人 (Haruto Otake) ● 経歴 ○ 2009~2013 ドワンゴ ○ 2013~ DeNA ■ ブラウザやUnity製ゲームの新規開発/運用 ■ 現在はUnity用ライブラリやSDK開発に従事
Slide 4
Slide 4 text
モバイルゲームのリソース基盤が 解決すべき課題
Slide 5
Slide 5 text
● 継続的なゲーム運営の為の差分管理 ● 巨大な初期ダウンロード ● アプリバイナリに組み込むリソースへの対応 ● コンテンツ保護と高速なロードの両立 ● アップデート実施までのリソースの秘匿 ● 開発のイテレーション速度を阻害しないビルド
Slide 6
Slide 6 text
● ゲーム運営の為の継続的なコンテンツ追加 ○ 月3,4回前後のイベント運用を行うには、アプリ更 新を伴わないリソース更新が必須 ○ ネットワーク経由でのリソース公開 ■ 必要な差分を適宜算出する
Slide 7
Slide 7 text
● 追加が主だが、既存リソースの 差し替えも発生 ● 更新のタイミングは利用者に依 る為、アップデート元が不定 ● DL途中のアプリ終了の考慮 ○ ダウンロード済みかどうかや、 ファイル破損のチェック実施 A B C B’ D E A' Ver.1 Ver.2 Ver.3 Ver.4
Slide 8
Slide 8 text
● 今のモバイルゲームでは1GB以上のダウンロード がインストールに発生してしまう事が多い ● 利用者に待ち時間を強いると、離脱に繋がる ● サイズが大きいと、利用者のモバイル通信容量を 無駄にする
Slide 9
Slide 9 text
● 必要に応じてダウンロードする戦略もあるが... ○ コンスタントに利用者の通信容量を消費する ○ 非同期にアセットを見せる等の工夫が必要 ○ すべての場面で適用出来るものではない
Slide 10
Slide 10 text
● チュートリアル用など追加DLを挟まずに利用し たいリソースはアプリに組み込みたい ○ iOSではAppStore規約上必須 ● Android / iOS共に、アプリバイナリへのリソー スの組み込みには一定の制限が存在
Slide 11
Slide 11 text
● Android ○ 2021年後半からAndroid App Bundle(AAB)の適 用が義務化(OBBが利用不可に) ○ OBBでは2GBまで配信可だが、AABでは150MB 以上は配信不可 ■ PlayAssetDeliveryの導入で1GB迄配信可 ○ apk(zip)として格納されるため、ファイルアクセス の手段に制限が生まれる
Slide 12
Slide 12 text
● iOS ○ AppStoreの規約上、起動時にAppが正しく機能 するよう、バイナリに十分なコンテンツを含む 必要 がある ■ チュートリアル等も含める為、巨大に ○ 2GBまで配信可 ○ OnDemandResources利用で+2GB迄配信可 ○ 通常のファイルシステムとして扱える
Slide 13
Slide 13 text
● 特に他社IPを使わせて頂くタイトルでは、暗号化 によるコンテンツ保護の仕組みが必要 ● 暗号化による負荷がゲーム体験を損ねないよう に、高速なロードを両立する必要がある ○ 特にUnityでは、長らくAssetBundleの暗号化と チャンク読み込みの両立が難しく、メモリを消費し がち
Slide 14
Slide 14 text
● ゲームからまだ利用されていないリソースがダウ ンロード可能になると、攻撃者から解析される ○ ”ネタバレ” / “解析” / “リーク” と呼ばれる ○ イベントやキャラなどの情報が、公式な情報公開 前に広まる可能性が高い
Slide 15
Slide 15 text
● リソースのビルド/デプロイが開発中の確認やリ リース作業を時間的に阻害するのを避ける ○ 運用してきた時間に比例してビルド対象物は線形 に増加する
Slide 16
Slide 16 text
● 継続的なゲーム運営の為の差分管理 ● 巨大な初期ダウンロード ● アプリバイナリに組み込むリソースへの対応 ● コンテンツ保護と高速なロードの両立 ● アップデート実施までのリソースの秘匿 ● 開発のイテレーション速度を阻害しないビルド
Slide 17
Slide 17 text
これらの課題をどう解決するか?
Slide 18
Slide 18 text
● 統合された1つのソリューションにせず、課題領 域を絞った複数のライブラリ/モジュールに分割 ● 全体を通して見たときに、利用側が前述した課題 を全て解決できている状態を目指す
Slide 19
Slide 19 text
● Aladin ○ 空間効率に優れたリソースのリビジョン管理 と暗 号化 ● AssetFetcher ○ HTTP/2によるリソースの並列ダウンロード ● Abdool ○ 高速な増分AssetBundleビルド & ロード
Slide 20
Slide 20 text
● ファイルベースのリソース管理ライブラリ ● 特徴 ○ Addressによるリソースへのアクセス ○ 複数のリビジョンのリソースを効率的に保持 ○ 高速なデプロイ ○ 様々なストレージへの対応と透過的な利用 ○ 透過的な暗号化 & 解析によるネタバレ防止
Slide 21
Slide 21 text
● 特定のリビジョンのリソース全 体をTreeと呼ぶ ● Tree毎に、Addressを識別子と した仮想的なストレージを持つ
Slide 22
Slide 22 text
● リソースの実体は中 身をハッシュ化した 値をファイル名にし てBlobとして保存 ● AddressとBlobの 紐付けをIndex として保持
Slide 23
Slide 23 text
● リビジョン間で共通するリ ソースは同一Blobで保持 ● 中身が同一なら、異なる Addressでも同一Blobで保持 ● 追加/変更差分のストレージ 消費のみで複数リビジョン を同時に保持可能
Slide 24
Slide 24 text
● ファイルを上書きしない 為、安全かつ高速なリビ ジョン切り替えが可能 ● 中身のハッシュ値とファイ ル名を比較するだけで破損 チェックが可能
Slide 25
Slide 25 text
● シリアライズしたIndexの ハッシュ値がリビジョン ● IndexもBlob同様にハッシュ 値をファイル名として保持
Slide 26
Slide 26 text
● ハッシュ値の先頭1バイトで サブディレクトリを作る ○ 大量のファイルを1つのディ レクトリに保存することによる パフォーマンス低下を回避
Slide 27
Slide 27 text
● Flatbuffersでデシリアライ ズ不要の問い合わせを可能に ○ メモリ軽減 ● Addressを64bitハッシュ化 ○ ソート済のFlatbuffers上のリ スト構造を直接二分探索
Slide 28
Slide 28 text
● Index同士の比較や、Indexに含まれるがストレー ジに存在しないBlobの特定 ○ ダウンロードが必要なリソースの特定に利用 ● 複数のリビジョンを指定して、どのTreeからも参 照されなくなったBlobの削除 ○ リビジョン更新後の旧リソースの削除に利用
Slide 29
Slide 29 text
1. CLIツールからTreeの形式にリソースを変換 2. 変換結果をディレクトリごとCDNにデプロイ 3. デプロイ先のベースURLと最新のリビジョンから IndexのURLを特定してダウンロード 4. Indexを読み込み、未ダウンロードなBlobを列挙 5. Blobをダウンロード 6. Treeが読み込み可能に
Slide 30
Slide 30 text
● 以前にデプロイしていないBlobのみを転送するだ けで済む為、極めて高速なデプロイが可能 ● 上書きが発生しないので、サーバー側に存在する ファイルは転送する必要がない ○ gsutils cpの-nオプションによって、サーバーに存 在しないファイルのみの転送を実現可能 ● デプロイ先のサーバーでも同時に多数のリビジョ ンを保持可能
Slide 31
Slide 31 text
● ストレージへの読み書きは抽象化して実装 ● アプリバンドルしたリソースとダウンロードした リソースを透過的に効率的に使い分ける ● 対応するストレージ ○ 通常のReadOnly/Writableなファイルシステム ○ AndroidのStreamingAssets ○ Play Asset Delivery
Slide 32
Slide 32 text
● Google Play Plugins for Unityを利用 ● Play Asset Deliveryの任意のAsset Pack内に保 存したAladinのTreeを読み込む ○ ファイルパスとOffsetとSizeを得られるため、範囲 を制限しただけのFileStreamとして少ないオー バーヘッドで読み込める
Slide 33
Slide 33 text
● アプリ同梱のリソースとダウン ロードしたリソースを完全に透過 的に扱う事を可能にする ● Decoratorによる宣言的な合成
Slide 34
Slide 34 text
No content
Slide 35
Slide 35 text
● 暗号化後のデータをBlobとして保存 ● 暗号化の実装は適宜入れ替えが容易に可能 ● 標準はランダムアクセス可能なストリーム暗号 ○ AssetBundle.LoadFromStreamに利用可能 ○ 暗号化利用時もチャンクロードが可能 ○ unsafeで高速,アロケーションフリーに最適化 ■ C#での相互運用性と速度を両立 ■ Unity特化版としてBurstへの対応も進行中
Slide 36
Slide 36 text
● クライアント内に隠した単一の鍵をコード解析等 で解読されるのが、ネタバレの主要要因 ○ 難読化しても、一度暴かれた時点でアウト ○ URLの難読化や、利用開始の直前までゲームか らダウンロードさせないことで以前は解決 ● 鍵をクライアントが知るのが不可能なら、解析耐 性は暗号化アルゴリズムの強度に依存
Slide 37
Slide 37 text
● 暗号化鍵を複数かつTreeとは独立して配布可能 ○ リソース毎に鍵IDを指定される ○ ランタイムで取得できるのは鍵IDのみ、鍵IDに紐 づく鍵情報は別途利用開始前に公開 ○ 公開済みの鍵は独自キーストアに格納 ● イベント開始前のリソースの柔軟な配布が可能 ○ 開始前に鍵を知ることが出来ないので、解読でき ない
Slide 38
Slide 38 text
● 継続的なゲーム運営の為の差分管理 ● 巨大な初期ダウンロード ● アプリバイナリに組み込むリソースへの対応 ● コンテンツ保護と高速なロードの両立 ● アップデート実施までのリソースの秘匿 ● 開発のイテレーション速度を阻害しないビルド Aladin Aladin
Slide 39
Slide 39 text
● 高速な並列リソースダウンローダ ● 特徴 ○ HTTP/2による高速並列ダウンロード ○ 様々な配信方式に幅広く対応 ○ ゲームエンジンを問わず利用可能
Slide 40
Slide 40 text
● 指定されたリソースをストレージに展開すること に特化 ○ URL,保存先,ハッシュ値の組のリストを受取る ○ 指定されたURLから並列にダウンロード ○ 結果のハッシュ値を計算し破損判定&リトライ ○ 保存先に展開 ● ダウンロードの必要性の判定は行わない ○ Aladin側ですべて判定可能
Slide 41
Slide 41 text
● HTTP/2では1接続で並列に大 量のリクエストとレスポンス のやり取りが可能 ○ 効率的に並列数を上げられ る為、受信完了から次の受 信開始までの時間が短い ○ 大量の小さなファイル向き イメージ図
Slide 42
Slide 42 text
● 旧来でも1ファイルにアー カイブすることで転送効率 は高められる ● Aladinのようにアーカイブ を行わない配信形式では HTTP/2は相性がよく、大 きな効果 イメージ図
Slide 43
Slide 43 text
163.93s から 20.93s HTTP/2での並列ダウ ンロードのあり無し で、約8倍もの差 5KB * 20000ファイル での計測
Slide 44
Slide 44 text
● 配信にサーバーの対応状況を確認する ○ 主要なCDNであれば殆ど問題ない ● nginxなどでリバースプロキシを挟むと速度が出 ないことがある ○ 開発用のIPアドレス制限などの利用に注意
Slide 45
Slide 45 text
● ZIPアーカイブ対応 ○ ダウンロードが完了したZIPの内容を、順番に保 存先ディレクトリに展開する ○ ZIP形式のパッチを順に適用する形式をカバー ● 独自アーカイブ(DnArchiver)対応 ○ リソース毎に圧縮の有無を選択できる独自のアー カイバでもZIP同様の運用が可能
Slide 46
Slide 46 text
● libcurlをバックエンドとして、C++で実装 ○ Unity向けにはネイティブプラグインとしてのイン ターフェースを用意 ● Unityはもちろん、内製エンジン(LiftEngine)を 含むその他のエンジンでも利用可能 ● macOS/Windows/Linux/iOS/Androidの5プラッ トフォームに対応
Slide 47
Slide 47 text
● 継続的なゲーム運営の為の差分管理 ● 巨大な初期ダウンロード ● アプリバイナリに組み込むリソースへの対応 ● コンテンツ保護と高速なロードの両立 ● アップデート実施までのリソースの秘匿 ● 開発のイテレーション速度を阻害しないビルド Aladin Aladin AssetFetcher
Slide 48
Slide 48 text
● AssetBundleビルド&ロードライブラリ ● 特徴 ○ VCSベースの高速インクリメンタルビルド機能 ○ シンプルなアドレッシングと最適化された独自カタロ グ管理 ○ 厳密な重複排除ポリシー ○ ResourceManagerベースの柔軟なロード機能
Slide 49
Slide 49 text
● Addressable Assets Systemの一部のみを利用 ○ AddressableのバックエンドであるResource Manager, Scriptable Build Pipelineを利用 ○ ロード状況を見れるEvent Viewerも利用 ● Addressable本体のAssetBundle管理機能は利用 しない
Slide 50
Slide 50 text
● Scriptable Build Pipelineでカスタムしたパイプ ライン ● Gitから以前のビルド以降で変化したアセットの リストを取得 ○ interface経由で他のVCSにも対応可能な設計 ● アセット間依存を元に、ビルドする必要のある AssetBundleを特定した上で実ビルド ● カタログを差分更新
Slide 51
Slide 51 text
アセットごとにグローバルなアドレスを設定可 カタログファイルのシリアライズには Flatbuffersを採用し、アロケーションを回避 カタログは非常に大量の文字列を含む 基数木による文字列保持を実装し、共通化 アセットの読み込みは文字列のハッシュのみを使 い、文字列比較を排除
Slide 52
Slide 52 text
● AssetBundleでは容易にアセットの重複が起こる ○ Addressableの場合ではAnalyzerで重複を検知 できるが、その代替が必要 ● ビルド中の全てのアセットに対して所属する AssetBundleが一意に定まれば重複しない ○ 所属するAssetBundleが定まらないアセットがビ ルドされた際にエラーとなるように
Slide 53
Slide 53 text
● AssetBundle構成はinterface経由で実装を注入 ○ バンドル名, ファイルパス, アドレスの組のリストを 返せることと、幾つかの逆引きも要求 ○ このinterfaceをPackRuleと呼ぶ ● フォルダ単位のシンプルな物は標準実装 ○ フレームワークやゲーム側でのポリシーにあわせ て個別に実装する
Slide 54
Slide 54 text
● Locatorを実装し残りはResourceManagerを利用 ○ Provider/Locatorの差し替えでカスタマイズ
Slide 55
Slide 55 text
● ResourceManagerの管理機構をそのまま利用 ○ ロード開始時に得られるHandleを ResourceManager.Releaseに渡すことで開放 ○ 参照カウントも行う為、同じアセットを複数ロードし ていても意識する必要はない ● AssetBundleは所属するアセットを全て開放した 時点で自動的に開放される
Slide 56
Slide 56 text
● Editorでの確認は 元アセットを AssetDatabase からロードしたい ○ Locatorの差替 ○ カタログを使わ ずPackRuleを 利用
Slide 57
Slide 57 text
● AssetBundle.LoadFromStreamを利用すること で、StreamからAssetBundleをロード可能 ○ 固定長の内部バッファの消費のみで、高速なラン ダムアクセスを行ってくれる ■ メモリフットプリントの大幅軽減 ■ 暗号化の計算量の大幅削減 ● Aladinの暗号化Streamを扱うことで実現 ○ 以前はAbdool側で実装していたが、全て移譲
Slide 58
Slide 58 text
● 専用のLocator /Providerを利用 ● 平文のものは通 常のProviderを 利用 ○ LoadFromFile が利用可なら こちらが軽量
Slide 59
Slide 59 text
● 継続的なゲーム運営の為の差分管理 ● 巨大な初期ダウンロード ● アプリバイナリに組み込むリソースへの対応 ● コンテンツ保護と高速なロードの両立 ● アップデート実施までのリソースの秘匿 ● 開発のイテレーション速度を阻害しないビルド Aladin Aladin AssetFetcher Abdool
Slide 60
Slide 60 text
● 設計に柔軟性を持たせて幅広いユースケースに対 応できるということは、ユースケース毎にそれに 応じた引数等を注入しなければならない ● 多くのタイトルに導入するにあたっては、これら を仲介する層が必要
Slide 61
Slide 61 text
● 内製フレームワークの一部、Sharin.Resourcesが 直接的なフロントエンド ○ Aladin, AssetFetcher, Abdoolを中心に他の基盤 モジュールも組み合わせ、よりユースケースを絞り 込んだフレームワークとして実装
Slide 62
Slide 62 text
● 実機確認のイテレーション問題 ○ リソースを実機確認する際にはアプリに組み込ん でビルドするか、サーバにアップロード&実機でダ ウンロードする必要がある ○ 少しずつ調整しながら実機確認をしたい場合に何 回もアプリをビルドorアップロード・ダウンロードす る必要がある ○ イテレーションが回しづらく開発効率が低下
Slide 63
Slide 63 text
● PC上のリソースを直接参照してしまう事で解決 ○ USB接続したPC上のリソースを実機のリソースの ように扱う 参照
Slide 64
Slide 64 text
Aladin Abdool Sharin.Resources AssetFetcher Sharin’の その他の様々な モジュール Abdool + Aladin インテグレーション vfs ゲームタイトル devwire DebugFileSyste mから利用 TechCon2020で の講演を参照
Slide 65
Slide 65 text
65
Slide 66
Slide 66 text
● フレームワークを導入しなくても、部分的に成果 を取り入れることが可能になる ○ Sharin.Resourcesを使わないタイトルでも、同じラ イブラリの導入に成功 ○ AssetFetcherに関しては非Unityでも導入済 ● 問題を小さなサンプルで再現が可能に ○ 問題のあるモジュールのみに集中できる ○ 自動テストがしやすく、問題解決が容易に
Slide 67
Slide 67 text
● ライブラリ側の責任範囲が限定的かつ明確になる ○ それぞれを単純化でき、柔軟性を担保可能 ○ 向き合う領域が単純な方が尖った設計を行えて、 競争力を持つ機能を開発できる ○ ゲーム側での“決め”になる部分をフレームワーク層 に委ねることができる ■ ライブラリが意思決定の速度的なボトルネックに なるのを避ける
Slide 68
Slide 68 text
● モバイルゲームのリソース管理基盤には様々な課 題がある ● 役割を絞って尖った機能性と柔軟性を持った様々 なライブラリを開発して課題解決を行った ● わかりやすいインターフェースのフレームワーク 層を提供して使い手側に寄り添っている
Slide 69
Slide 69 text
No content