Slide 1

Slide 1 text

『プロジェクトセカイ カラフルステージ! feat. 初音ミク』 3周年大型アップデートでの パフォーマンス最適化事例 1 プロジェクトセカイ カラフルステージ! feat. 初音ミク 山口 智也 クライアントエンジニア 大河原 壱成 クライアントエンジニア

Slide 2

Slide 2 text

『プロジェクトセカイ カラフルステージ! feat. 初音ミク』について 2

Slide 3

Slide 3 text

3 プロジェクトセカイ カラフルステージ! feat. 初音ミク ユーザー数 1000万人超 X(旧Twitter) フォロワー数 200万人 公式YouTube チャンネル 登録者数 156万人 ● 『初音ミク』と『人間』が織りなす新しい 物語・新しい展開 ● 2D・3D・Live2D−− それぞれ描かれる魅力的な キャラクターたち ● VOCALOID曲を中心に有名楽曲を多数収録した リズムゲーム ● 数多の著名クリエイターから提供される楽曲・ クリエイティブ 魅力的なキャラクター(シナリオ・イラスト)× リズムゲーム

Slide 4

Slide 4 text

3周年大型アップデート内容 4

Slide 5

Slide 5 text

5 3周年大型アップデート内容:3Dアップデート ● アセットの改良(キャラクターモデル、テクスチャ等)    ほぼ全てのモデルを作り直し ● 表現機能開発(キャラシェーダ、ポストプロセス等)    演出表現をアップデートし、全てのMVをアップデート  “プロジェクトセカイ ワンダショちゃんねる 3周年スペシャル” より抜粋

Slide 6

Slide 6 text

6 3周年大型アップデート内容:UIリニューアル ● 全ての画面のUIをアップデート ● 各画面でUX向上のための機能を追加 ● グラフィックス表現の向上

Slide 7

Slide 7 text

最適化について 7

Slide 8

Slide 8 text

8 最適化をおこなう理由 快適に遊べるように最適化が必要! ● ほぼ全てのモデルをアップデート ● 全てのMVをアップデート ● 全ての画面のUIをアップデート ● キャラシェーダ、ポストプロセスの 開発 3Dアップデート UIリニューアル ● グラフィックス表現の向上 大量のアセット改修 アセット管理が適切におこなわれていない ⇒アプリクラッシュに繋がる 処理負荷の増加 処理負荷を軽減していない ⇒ゲームが重くUXに影響

Slide 9

Slide 9 text

9 タイプ別の最適化 定常負荷の削減 フレームレートの低下・過剰な発熱を防ぐ スパイクの軽減 1フレームで走る処理時間の長い処理の改善 メモリ使用量の削減 メモリリークを防ぎ、メモリが許容量を オーバーしないようにする

Slide 10

Slide 10 text

10 最適化事例 ● 最適化でおこなった内容を   3D最適化   アウトゲーム最適化  の順に分けて説明 ● 以降対応した事例ごとにタグ付けをおこない、    最適化をおこなった背景と対処法を紹介 定常負荷の削減 スパイクの軽減 メモリ使用量の削減

Slide 11

Slide 11 text

3D最適化 11

Slide 12

Slide 12 text

12 アセットのロード、アンロード処理 スパイクの軽減 ロード アンロード ・インゲームで扱うアセットを  全てロードする ・GC処理は停止する ・オブジェクトの参照関係を  事前に解決する ・インゲームに関わる処理のみ実行 ・インゲーム中のアセットは  すべて破棄 ・GCの再開 背景 演出が増え、MVごとに使用するアセットが増加した 対処 ● 必要なアセットはMV再生前に事前ロードする ● インゲーム中はGC止める ● リズムゲーム中にロードやGCによる解放処理でスパイクが発生する可能性がある

Slide 13

Slide 13 text

13 演出機能の改修 定常負荷の削減 背景 : 今まで単体機能として処理した特定領域へのカラー合成機能を重ねがけたい     ポストプロセス処理のため、そのまま処理すると 複数回フルスクリーン描画が走ることで処理負荷が増大する 対処 : フルスクリーン描画を避け、フラグメント処理を削減 カラー合成機能は 画面端から効果を かけることが多い 合成1 合成2 合成3

Slide 14

Slide 14 text

14 演出機能の改修(DoF) “プロジェクトセカイ ワンダショちゃんねる 3周年スペシャル” より抜粋 定常負荷の削減 背景 前景が綺麗にボケてほしい、カメラ構造に従ったパラメータで調整したい ・Unity標準のBokeh DoFは採用できず(ミドル端末で60fps安定⇒40fpsまで低下) 対処 カスタムした、GaussianベースのDoF処理を採用 ⇒ 60fps安定することを確認 実装の詳細は Colorful Palette Advent Calendarに記載しています。

Slide 15

Slide 15 text

15 レンズフレア(新機能)の最適化 背景 オブジェクトとの遮蔽判定をもつフレアを表現したい ● フレアごとの遮蔽判定処理、半透明描画をおこなう必要がある レンズフレアの最適化前  メッシュ...CPUで1フレアごとにMeshを生成し、Dynamic BatchingによりMeshを結合  遮蔽判定...Raycastを使用し、1フレアごとにRayをとばして判定する 対処 ・深度バッファを使用した遮蔽判定により  Raycastで判定するための大量の  Collider判定処理が不要に ・DrawProceduralを使用し、  Meshの生成、結合処理を削減 ・ComputeShaderを用い、  RaycastによるCPU負荷を削減 定常負荷の削減 NEO / 星乃一歌 × 花里みのり × 小豆沢こはね × 天馬司 × 宵崎奏 × 初音ミク【3DMV】 参考:「IDOLY PRIDE」における描画最適化術

Slide 16

Slide 16 text

16 カメラ負荷削減 背景 Unityのカメラ処理がボトルネックに ● カメラ1個ごとに描画前のCPU処理、GPU描画処理が発生する    CPU処理では特にカリングが負荷大 ● ローエンド寄りのモバイル端末では、カメラ1つで最大1msのCPU処理が発生する ことも 対処 ● 使用していないカットではカメラ処理を走らせない ● カメラ数を削減する  ⇒次ページより事例紹介 定常負荷の削減

Slide 17

Slide 17 text

17 対処 使用していないカットではカメラ処理を走らせない ● プロジェクトセカイではメインのカメラの他に、サブのカメラが存在する ● 1MVでも使用するカットが限られるので、サブカメラ不使用時は処理しないように カメラ負荷削減 定常負荷の削減 サブカメラ使用時は処理する サブカメラ不使用時は処理しない

Slide 18

Slide 18 text

18 対処 カメラ数を削減する ● カメラに追従するオブジェクトの描画を別カメラでおこなっていた ● 最終的なレンダーターゲットは同じなので、カメラを分けずに対応可能 カメラ負荷削減 定常負荷の削減 対応前 対応後

Slide 19

Slide 19 text

19 半透明シェーダのOverdraw軽減 背景 ライブステージのスポットライトなど、 アルファが0のまま表示されている半透明オブジェクトが多くあった →Overdrawの削減が可能であると判断 対処 半透明用のシェーダに機能追加を行って対応 アルファのプロパティの値が0の場合、頂点シェーダでスケールを 0にしてフラグメントの描画をカットするようにした 定常負荷の削減

Slide 20

Slide 20 text

20 ShaderVariantの見直し メモリ使用量の削減 背景 ランタイム処理最適化のために機能ごとのShaderVariantを 定義していたが、量が多く、多くのメモリを消費していた ShaderVariantについて ・Shader内にKeywordを定義することで、  Keyword有効無効時の処理分岐を考慮した  Shaderを1ファイル内に記述することができる ・Keyword有効無効を考慮した全ての組み合わせを  網羅するShaderProgramがプリコンパイルされる  ため、Keywordを追加する度に指数関数的に消費  メモリが増加する 開発中のポストプロセスシェーダ消費メモリ ShaderVariant Keywordの定義と実行例 リズムゲーム中スパイクを発生させないように 全ての組み合わせをプリコンパイルする 7個のShaderKeywordを定義すると、2^7=128パターンのShaderファイルをコンパイルする必要がある 10個のShaderKeyword定義 … 2^10=1024パターンに...

Slide 21

Slide 21 text

21 ShaderVariantの見直し 対処 ShaderVariantを削減する ● 計算負荷の低い処理は常時処理する ● 分岐条件がUniform変数の場合、通常のif文で処理する(Static Uniform Branch) メモリ使用量の削減 ↓Variant削減後 最適化後のポストプロセスシェーダ消費メモリ 210.3MB ⇒ 471.7KBに削減 全てのピクセル処理で同じ分 岐を通る場合、分岐コストは 抑えられる コンパイル時分岐考慮済みの Shaderを実行するため、ラン タイム中の分岐コストは0 ピクセルごとに異なる分岐を通る場合、 分岐コストは高い

Slide 22

Slide 22 text

22 インゲーム中のシェーダのコンパイル回避 スパイクの軽減 背景 インゲーム中シェーダコンパイル起因のスパイクが発生した シェーダのコンパイルが発生する理由 ● 基本的にShaderは描画命令が出たタイミングでコンパイルをおこなう ● 定義したShaderVariantのうち、初めての組み合わせが発生した瞬間に コンパイル処理が実行される 上記2つは組み合わせが異なるので、実行時それぞれコンパイルが発生する ⇒全ての組み合わせごとに初回時コンパイルが発生することに...

Slide 23

Slide 23 text

23 インゲーム中のシェーダのコンパイル回避 スパイクの軽減 対処 MVロード時ShaderVariant.Warmupによるプリコンパイルをおこなう ● Keywordはマテリアル単位で定義し、Global定義は使用しない ● インゲーム中使用するShaderと全ての組み合わせをShaderVariantCollectionに登録 MV再生開始 ShaderName Normal Normal A Normal B Normal A B Keyword定義したシェーダ 全てのシェーダ、全ての Keywordの組み合わせを 登録する 楽曲選択 ロード ShaderVariantCollection.Warmup で登録した全組み合わせに対する Shaderのプリコンパイルをおこなう

Slide 24

Slide 24 text

24 圧縮形式 背景 1MVにロードするアセットが増え、 消費メモリに懸念が生じた 対処 役割ごとにテクスチャの圧縮サイズ(ASTC)を設定  実機上の見た目を最優先に考慮しつつ、  用途によって圧縮倍率を設定 例: Shaderでの計算処理用マップ…ASTC4x4 キャラクターやエフェクトのカラーマップ…ASTC6x6 メモリ使用量の削減 https://developer.nvidia.com/astc-texture-compression-for-game-assets NVIDIAが公開している 圧縮形式、サイズごとの視覚的評価

Slide 25

Slide 25 text

事例 : アウトゲーム最適化 25

Slide 26

Slide 26 text

26 アウトゲームを最適化する際に意識したポイント 操作時のストレスをなるべく削る 画面遷移をスムーズに、操作を快適に → 各種操作でのスパイクを削っていく 長時間のプレイに耐えらえるようにする 特にADVシーンは滞在時間が長い → 定常負荷が上がることでの発熱を抑えていく → メモリリークによるクラッシュを防ぐ

Slide 27

Slide 27 text

27 操作時のスパイクの軽減 背景 画面遷移や各種操作のたびに待たされるストレスの軽減のため スパイクをなるべく削っていく必要がある しかし、最適化にかけられる時間は限られている 対処 プレイヤーが触る頻度が高い部分(特にメインループ)を 重点的に調査・最適化していく 主に処理の並列化、フレーム分散、ロジックの最適化等で対応 スパイクの軽減

Slide 28

Slide 28 text

28 マスタデータのメモリ最適化 背景 ロード等の高速化のためマスタデータがオンメモリになっていた → 長期間の運用・アプデによってサイズが肥大化 対処 一部マスタデータをストレージから適宜ロードするように変更 アクセス頻度が低くサイズが大きいデータを重点的に対応 メモリ使用量の削減

Slide 29

Slide 29 text

29 アセットのメモリリークの解消 背景 通常アセットは画面を抜ける時にアンロードされるが、 static変数やSingletonで参照が握られているアセットのリソースが 解放されない関係で一部リソースがメモリに残り続けることがある → 一度特定画面に入るとメモリ使用量が増加する事態が発生 対処 Memory Profiler等でのプロファイリングを元に地道に解消 全てを解消することは難しいため、コスパを意識しながら対応 メモリ使用量の削減

Slide 30

Slide 30 text

30 積み上がるアセットの都度破棄 背景 各画面でロードされたアセットは 基本画面を抜けるときにアンロードされる → 1画面で大量にロードされる可能性があるアセットが存在する   (楽曲選択画面での楽曲ジャケット画像など) 対処 固定サイズのリングバッファを用意し、 古くなったもの(サイズオーバーしたもの)から 逐次破棄していくようにした メモリ使用量の削減 楽曲選択画面

Slide 31

Slide 31 text

31 TextMeshProのMesh生成の頻度を下げる 背景 ADVシーンの字幕UIでタイプライター風の表現が行われている → 文字数が増えるたびにTextMeshが再生成されてしまっていた スパイクの軽減 タイプライター風表現

Slide 32

Slide 32 text

32 TextMeshProのMesh生成の頻度を下げる 対処 最大文字数分のTextMeshを事前に生成しておき、 各文字用の頂点の座標を変更 (個別にスケールを0にするイメージ) することで表示・非表示を切り替える方式に変更 スパイクの軽減 こ ん に 非表示の文字の頂点のスケールを0にする

Slide 33

Slide 33 text

33 UIブラーのブラー処理の頻度調整 背景 UIリニューアルのために実装された新機能 開発中は毎フレーム画面をキャプチャしブラー処理を行っていた → アウトゲームでのGPU負荷が課題になった 定常負荷の削減 UIブラー表現

Slide 34

Slide 34 text

34 UIブラーのブラー処理の頻度調整 対処 原則ブラー表示開始時にキャプチャした画面を使い回す構造に変更 (ブラー背景が動かなくなることを許容した) 定常負荷の削減とUI表現のトレードオフを加味した最適化 定常負荷の削減 画面 キャプチャ + ブラー ブラー表示開始タイミング 前面UI ブラー表示中

Slide 35

Slide 35 text

35 不要な描画の洗い出し・削減 背景 アウトゲーム上の描画の定常負荷を削減するため、 FrameDebuggerで最適化箇所の洗い出しを行った → 特定カメラが不要なタイミングで描画されていることがあった 対処 各カメラの描画が必要なタイミングの整理を行い カメラの描画が必要ない画面ではカメラを無効化するように変更 例 : ガチャ画面ではSpine等が表示されるエリアのカメラは不要なので無効化 定常負荷の削減

Slide 36

Slide 36 text

36 UI・2D描画のOverdrawの削減 背景 プロジェクトセカイではアウトゲームの描画解像度が高いため、 フィルレートがGPU負荷のボトルネックになっていることが多い → 2D画面・UI描画におけるOverdrawを削っていく必要があった 定常負荷の削減 Overdrawが多いシーンの例

Slide 37

Slide 37 text

37 UI・2D描画のOverdrawの削減 対処 Overdrawのデバッグ表示で最適化が有効な箇所を洗い出す ● サイズの大きいUIパーツが複数重なっているところを結合する ● 画面占有率が高いパーティクルを減らす など、クリエイターと協力しながら地道に最適化 定常負荷の削減 複数のパーツを結合する

Slide 38

Slide 38 text

38 まとめ ● 3周年アップデートにより、大幅なアセット改修、システム改修をおこなった ○ どこで処理負荷が増大しているか等見直す必要がある ● ユーザに快適に遊んでもらえるように、最適化をおこなった ○ 最適化はゲームを快適にプレイできるようにするために必要 ● 最適化事例を事例ごとに紹介 ○ 3D、アウトゲームに分けて紹介した ○ 実際にプレイして問題を洗い出し、それぞれ対策をおこなった