Slide 1

Slide 1 text

Unity+スマホで3Dゲーム開発/最適化 するための考え方 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE 株式会社Cygames エンジニア 金井 大

Slide 2

Slide 2 text

自己紹介 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 金井 大 • 技術研究チーム所属のエンジニアです • VR、ゲームエンジン、グラフィックスとかの研究 開発してます

Slide 3

Slide 3 text

アジェンダ $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • Unity + スマホで3Dゲーム開発/最適化する ための考え方を、以下で紹介します – 開発の指針 – 構成およびスペックの一例 – 開発と最適化のためのTIPS – 指針と手法の答え合わせ

Slide 4

Slide 4 text

開発の指針 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 5

Slide 5 text

大事なこと $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 端末の性能を把握する • コンテンツの要素を把握する – 適切な単位で区切り – コストを把握し – そのコストを最適化する • 要素を選択できるようにする

Slide 6

Slide 6 text

UNITY HARDWARE STATISTICS $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 出典:http://hwstats.unity3d.com/mobile/ • unity mobile stat で検索

Slide 7

Slide 7 text

詳細 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • Mali 400 MP: 20.0% • Adreno 305: 12.5% • PowerVR SGX543: 10.9% • Apple A7: 8.5% • Adreno 330: 5.9% • Adreno 306: 5.4% • Apple A8: 4.7% • PowerVR SGX544: 4.1% • Adreno 320: 2.8% • Vivante GC1000: 2.3% • Videocore IV: 2.2% • Mali 450 MP: 2.1% • Mali T760: 2.1% • PowerVR SGX540: 1.6% • PowerVR SGX531: 1.5% • Adreno 203: 1.4% • PowerVR SGX535: 1.3% • Adreno 200: 1.2% • PowerVR SGX554: 1.0% • Adreno 225: 0.9% • Adreno 405: 0.8% • Mali T628: 0.7% • Apple A8X: 0.6% • PowerVR G62xx: 0.5% • Mali T624: 0.5% • Tegra 2: 0.5% • Intel HD BayTrail: 0.4% • Adreno 220: 0.4% • Vivante GC2000: 0.4% • BlueStacks ES2.0 Emu: 0.3% • Tegra 3: 0.3% • Mali 300: 0.3% • Mali T720: 0.3% • Mali T622: 0.2% • Adreno 205: 0.2% • PowerVR G64xx: 0.2% • Adreno 420: 0.2% • Adreno 430: 0.1% • Immersion.16: 0.1% • Adreno 418: 0.1% • Vivante GC7000: 0.1% • Vivante GC800: 0.1% • Something strange: 0.1% • Adreno 304: 0.0% • PowerVR SGX530: 0.0% • Vivante GC4000: 0.0% • Android ES Emulator (GeForce): 0.0% • Tegra 4: 0.0% • Mali T604: 0.0% • Android ES Emulator (Radeon): 0.0%

Slide 8

Slide 8 text

3DMARK $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 出典:http://www.futuremark.com/hardware/mobile/ • 3DMARK mobile results で検索

Slide 9

Slide 9 text

3DMARK $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 拡大

Slide 10

Slide 10 text

どうしてこうなった $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • キャリア • チップセット • CPU – コア数 – クロック • GPU • メモリ

Slide 11

Slide 11 text

PCゲームのグラフィックス設定 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 出典: http://doope.jp/media/15q1/img2826_01.j pg

Slide 12

Slide 12 text

$POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • どこまでユーザーに選択させるか?

Slide 13

Slide 13 text

スマホでの現実解は? $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • ある程度は大まかに制御したい – エフェクト ON/OFF – 効果音 ON/OFF – FPS – スペックの抽象化

Slide 14

Slide 14 text

$POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 「スペックの抽象化」ってなんやねん

Slide 15

Slide 15 text

例えばシェーダーを例に $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • Vertex shader – カラーアニメーション – UVアニメーション – アウトラインメッシュの法線方向への拡大 – セルルック • Fragment shader – イメージエフェクト – スキンシェーダー – ノーマルマップ – セルルック

Slide 16

Slide 16 text

アプリケーションでの抽象化 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • Vertex shader – カラーアニメーション – UVアニメーション – アウトラインメッシュ – セルルック • Fragment shader – イメージエフェクト – スキンシェーダー – ノーマルマップ – セルルック 低スペック 高スペック 使わない

Slide 17

Slide 17 text

端末に落とし込む $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • Vertex shader – カラーアニメーション – UVアニメーション – アウトラインメッシュ – セルルック • Fragment shader – イメージエフェクト – スキンシェーダー – ノーマルマップ – セルルック 低スペック 高スペック 使わない iPhone5s iPhone6 iPhone6s Galaxy  S5 Galaxy  S6

Slide 18

Slide 18 text

大事なこと $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 端末の性能を把握する • コンテンツの要素を把握する – 適切な単位で区切り – コストを把握し – そのコストを最適化する • 要素を選択できるようにする

Slide 19

Slide 19 text

構成およびスペックの一例 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 20

Slide 20 text

目標 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 60fpsをキープしたい • キャラクターを5体表示 • 絵力 – フェイシャル – モーションキャプチャー – 他と差別された強い絵力が欲しい! • タイトなスケジュールに負けない

Slide 21

Slide 21 text

より現実的なゴール $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 低スペック端末では – 幅広く動作するようクオリティぎりぎりまでスペック を落としつつ60fpsをキープ • 高スペック端末では – 高性能端末で高品質な画面を提供しつつ60fpsを キープ

Slide 22

Slide 22 text

キャラクター $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • スペック – テクスチャ • ETC1(αチャンネルなし)/PVR • Mipmapなし(データサイズ縮小のため – ウェイト • 基本は2ボーン – 3ボーンをPlayerSettingで2にするとメッシュが崩れることがあ る

Slide 23

Slide 23 text

キャラクター $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • フェイシャル – ボーン制御 – Animatorで眼球、リップの動きを用意し、外部から 制御 – 眼球の追従先をプログラム制御 • アウトライン – アウトラインメッシュ – 頂点カラーでの調整 – リムライト、セルルックは…? • 造形が良ければアウトラインでも

Slide 24

Slide 24 text

キャラクター $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • クロス – 独自実装 – それなりに重いので、まずはC#でチューン • 計算部分のみなら22行程 – マルチスレッド化できるようにデータ局所化 – あとはネイティブプラグイン化すれば…

Slide 25

Slide 25 text

背景 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • テクスチャ – 基本はETC1(αチャンネルなし)/PVR – Mipmapあり – UVアニメーション用に3MB程度を確保 • 画面キャプチャ – ImageEffectで作成した中間バッファを流用 – 1フレーム遅れた絵になるが低コスト

Slide 26

Slide 26 text

その他 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • ライティング – 基本的にはライティングしない – アンビエント – 板を1軸回転してカメラに向けてボリュームライトっぽく • シャドウ – リアルタイムシャドウは断念 – 板ポリの安いやつ。Diffuseに焼く。 • ないと立体感なくなります • パーティクル – 一定数まとまったメッシュを用意 – パーティクルとして降らせる – Vertex shaderで動きをつける

Slide 27

Slide 27 text

Image Effect $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • ImageEffect – DOF(被写界深度 – Bloom – カラーコレクトはオミット • Unityのシェーダーをベースに – 1カメラで実現できるようカスタマイズ – ついでに高速化

Slide 28

Slide 28 text

Directシーン $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • キャラクターや背景の任意組み合わせを確認でき る専用シーン • デザイナー/プランナーの作業、確認が主用途 • 各種アセットのデータ形式に対応 – 通常アセット – アセットバンドル(サーバー上 – アセットバンドル(ローカルPCにつくったやつ • 端末でも動作可能 – アプリ本体を経由しないので、単体テストやコスト計測 にも使える

Slide 29

Slide 29 text

開発と最適化のTIPS $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 30

Slide 30 text

計測 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 31

Slide 31 text

Unity Profiler $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 32

Slide 32 text

Statistics $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 33

Slide 33 text

FrameDebugger $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • DrawCallを確認可能 – Unity5から こ の へ ん が 描 画 リ ク エ ス ト

Slide 34

Slide 34 text

GPU Profiler $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 描画系の追跡はUnity Profilerでは限界がある – オーバーヘッド – GPUのプロファイルに難アリ • チップセットと対になったGPU Profilerを使う – iOS -> instruments / OpenGL ES Frame Debugger – Adreno -> Adreno Profiler – Tegra -> PerfHUD ES • 端末や要素の性能を把握できる

Slide 35

Slide 35 text

例:Adreno Profiler $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 36

Slide 36 text

Adreno Profiler $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • プロファイルした情報を保存することが可能 – チューニング前後の比較に • 頂点データ/テクスチャの保存 • シェーダーの可視化と変更 • Etc…

Slide 37

Slide 37 text

Adreno Profiler $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • FrameDebuggerと同じくDrawCallが目視で きる

Slide 38

Slide 38 text

Adreno Profiler $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • フレームバッファ、テクスチャのキャプチャ • シェーダー修正

Slide 39

Slide 39 text

Adreno Profiler $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • FPSやGPU使用率などをグラフ化

Slide 40

Slide 40 text

描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 41

Slide 41 text

描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • おおざっぱに以下のように考える – vertex負荷 = (描画リクエストされた頂点数) x (vertex shaderの命令数) – fragment負荷 = (描画されたピクセル数) x (fragment shaderの命令数) – 厳密にはパイプライン次第だと思う • 各ベンダー/各世代のチップ考慮するのは大変なので

Slide 42

Slide 42 text

描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 出典: http://climserv.ipsl.polytechnique.fr/documentation/idl_he lp/images/shader_detail.gif

Slide 43

Slide 43 text

描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 例:球(4000頂点)を(1/1)と(1/4)で描画し た時の比較 – vertex負荷は同じ – fragment負荷は約1/16になる

Slide 44

Slide 44 text

描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • vertex負荷の制御はデリケート – 描画対象となる頂点数を減らしたい – 何らかで頂点数を削れば良いのだが… • データ削減するとシルエット崩れや作業コストが懸念 • カリング精度を上げるにはCPU/GPU負荷が懸念 • fragment負荷は比較的制御しやすい – 描画面積とシェーダーで制御できる – カメラワークには注意

Slide 45

Slide 45 text

描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • vertexは最初から低めに抑さえる – 特に低スペック端末を考えると低めにせざるを得 ない – 最低限のLODデータを用意する • fragment負荷を制御できる手段を用意する – ImageEffectをOn/Offする – 画面解像度を制御する – Meshのfragmentシェーダーを軽量版に切り替える

Slide 46

Slide 46 text

描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 47

Slide 47 text

描画順の制御 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 48

Slide 48 text

描画順の制御 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 前提として「描画順」と「ZTest」を理解する – ZTestが有効な場合、隠れたfragmentは描画されない • 1がZ値的に手前にある時、1を描いてから2を描 くと、一部は描画されない 2 1

Slide 49

Slide 49 text

描画順の制御 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 極端にすると。 • 1を描画してから2を描くと、2は殆ど描画されな い 2 1

Slide 50

Slide 50 text

隠れているのがポイント $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • アウトラインメッシュの描画が無駄になるので • こういう順番にしたい

Slide 51

Slide 51 text

描画順の制御 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 不透明は(基本的には)手前から描く – 隠れた個所はfragmentシェーダーが走らない – 基本的にUnity側が手前からソートしてくれてる

Slide 52

Slide 52 text

描画順の制御 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • なんだけど – 原点位置を基準にソーティングする – 意図した結果になるとは限らない – こういう時は床を最後にしたいが原点基準だと。。。

Slide 53

Slide 53 text

描画順の制御 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • Unityで描画順を制御する手段 – Camera.depth – MeshRenderer.sortingLayerName – MeshRenderer.sortingOrder – Material.renderQueue

Slide 54

Slide 54 text

描画順の制御 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 優先としては以下になる Camera.depth sortingLayerName =“default” sortingOrder =0 renderQueue=2000 renderQueue=2010 renderQueue=3000 sortingOrder =100 renderQueue=2000 renderQueue=2010 renderQueue=3000 sortingLayerName =“after” sortingOrder =10 renderQueue=2000 renderQueue=2010 renderQueue=3000 sortingOrder =200 renderQueue=2000 renderQueue=2010 renderQueue=3000

Slide 55

Slide 55 text

Camera.depth $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • CameraはCullingMask設定が必要になるなど、 色々面倒 – ImageEffect使用時は注意! • Camera.clearFlags=Depthだとclearが劇重 • GPU20%程度の消費することも

Slide 56

Slide 56 text

MeshRenderer.sortingLayerName $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • sortingLayerNameは以下で追加可能 – Layers -> Sorting Layers • 記載の順番に処理される

Slide 57

Slide 57 text

MeshRenderer.sortingOrder $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 同じsortingLayerNameでの描画順 • sortingLayerNameと合わせて運用を考える

Slide 58

Slide 58 text

Material.renderQueue $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • マテリアル単位で描画順を制御する • Material.renderQueueはシェーダーからも設定可能 – Tags {"Queue"="Geometry-1" "RenderType"="Opaque"} • Queueは文字列に見えるけど実際は数値 – Background = 1000 – Geometry = 2000 – AlphaTest = 2450 – Transparent = 3000 – Overlay = 4000 • なので、前述の例は「1999」になる

Slide 59

Slide 59 text

こんな事も $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 「髪の毛より手前にある眉」

Slide 60

Slide 60 text

髪の毛より手前にある眉 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 髪の毛に隠れてしまう眉毛を何とかして手前 に出したい – ZTest / ZWriteをOffにして対処 – ZTestしないので、「必ず」最前面に眉が描かれる (髪の上に描かれる) – ZWriteしないので、他のオブジェクトにZ値干渉し ない

Slide 61

Slide 61 text

髪の毛より手前にある眉 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 弊害として、他キャラの眉毛が貫通してくる可 能性がある – 描画順を制御して奥から描く • キャラA頭 • キャラA眉 • キャラB頭 • キャラB眉 • …

Slide 62

Slide 62 text

髪の毛より手前にある眉 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 問題はいくつか残る – 頭と眉の形状によっては、自キャラの眉が貫通して くる • カメラワークでの回避 – 無駄な描画が発生する • 我慢する

Slide 63

Slide 63 text

SetPassとDrawCall $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 64

Slide 64 text

DrawCall $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • まずDrawCall – GPUへ描画リクエストする、ということ – 固有のマテリアルを描画リクエストすると 1DrawCall消費する – Unity5からStatisticsより消失しました

Slide 65

Slide 65 text

$POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 「固有のマテリアルを描画リクエストするとDrawCall 消費する」ってなんやねん • 「固有のマテリアル」ってなんやねん

Slide 66

Slide 66 text

DrawCall $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 固有のマテリアルとは – UnityEngine.Materialのメンバがユニークであるこ と – 例えば • Colorが異なる • Textureが異なる • Shaderが異なる • Etc… – 他と異なるメンバがあれば、それは固有である

Slide 67

Slide 67 text

DrawCall $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • BOX全体にマテリアルA → DrawCall=1 • BOX各面にマテリアルABC → DrawCall=3 A A B C

Slide 68

Slide 68 text

DrawCall $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX全体にマテリアルA)x2 → DrawCall=2 • (BOX各面にマテリアルABC)x2 → DrawCall=6 A A B C A A B C

Slide 69

Slide 69 text

DrawCallとバッチ処理 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 同じマテリアルだったら最適化できそう • そこでバッチ処理 • 同じマテリアルをもつドローコールを統合する

Slide 70

Slide 70 text

DrawCallとバッチ処理 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX全体にマテリアルA)x2 → DrawCall=1 A A

Slide 71

Slide 71 text

DrawCallとバッチ処理 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX各面にマテリアルABC)x2 →DrawCall 数は描画順に依存する(後述) A B C A B C

Slide 72

Slide 72 text

DrawCallとバッチ処理 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • バッチ処理は2種類ある • StaticBatch – 移動しない同一マテリアルを持つメッシュをマーキングし、 事前にバッチ用のデータをしこむ – 統合の効果が高いが、移動したりマテリアル操作するメッ シュには適応できない • DynamicBatch – 前後のドローコールが同一マテリアルをもつ場合、ランタイ ム時に統合する – ランタイムに行うのでCPUコストがそこそこある – StaticBatchより効果が低い(頂点数等の制限数がある) • http://docs.unity3d.com/ja/current/Manual/DrawCallBatchin g.html

Slide 73

Slide 73 text

DynamicBatch $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • DynamicBatchの注意点 – 前後のドローコールが同一マテリアルを持たないと統 合しない – 描画順によっては統合できない! – 例えば描画順が以下だと統合されない • BOX(マテリアルA • BOX(マテリアルB • BOX(マテリアルC • BOX(マテリアルA • BOX(マテリアルB • BOX(マテリアルC • DrawCall=6になる

Slide 74

Slide 74 text

DynamicBatch $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 描画順が以下であれば統合される – BOX(マテリアルA – BOX(マテリアルA – BOX(マテリアルB – BOX(マテリアルB – BOX(マテリアルC – BOX(マテリアルC – DrawCall=3になる • 描画順は前述のsortingOrderで制御可能

Slide 75

Slide 75 text

DrawCall $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • DrawCallを減らすのであれば、描画時に固有 マテリアルが連続するよう、ルールを決めてお く – Batch処理を利用する – sortingOrder等で描画順を制御する – そもそも固有マテリアルを減らす • テクスチャを共有化する • シェーダーを共有化する • 変更するパラメーターを限定する • Etc…

Slide 76

Slide 76 text

SetPass $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • SetPassとは – よりパフォーマンスの指針となる数値 – DrawCall時に前回使用したマテリアルから変更が あった場合、1SetPass消費する

Slide 77

Slide 77 text

SetPassとDrawCall $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 【Unity】Unity Performance Casual Talk 「ド ローコール伝説の終わり」 レポート – http://qiita.com/baba_s/items/5260807ced7fc3c02ca 6

Slide 78

Slide 78 text

SetPassとDrawCall $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX全体にマテリアルA)x2 → SetPass=1 • バッチに依存せず、SetPassは1になる A A

Slide 79

Slide 79 text

SetPassとDrawCall $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX各面にマテリアルABC)x2 → SetPassは描 画順に依存する • SetPassを減らすにはDrawCallと同じく描画順を 意識する • DrawCallと同じノウハウが利用できる A B C A B C

Slide 80

Slide 80 text

Depth Texture $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 81

Slide 81 text

Depth Texture $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • ImageEffectの被写界深度はZ値を参照してボカ シ処理を行う • Z値を参照するには、DepthTextureが必要 – Camera.depthTextureMode = DepthTextureMode.Depth; • 注意点 – DepthTextureはRenderTargetへ描画を行うことで 生成されてる – DepthTextureへポリゴンを描いている、ということ – 単純に描画頂点数が二倍になる

Slide 82

Slide 82 text

Depth Texture $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • DepthTextureへの描画時に利用されるシェー ダーは? – シェーダー中のTagsを参照してます • http://docs.unity3d.com/ja/current/Manual/SL- ShaderReplacement.html – UnityにLightModeというタグが用意されており、以 下タグを持つSubShaderに置き換わる • Tags{ "LightMode" = "ShadowCaster" } – Unity4 -> 5で変更された箇所なので注意

Slide 83

Slide 83 text

Depth Texture $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • ShadowCasterシェーダーを実装する理由 – アウトライン+DOF時に必要となる事がある – キャラクターはアウトライン分微妙にサイズが大き くなる • ので、DepthBufferに書き込む大きさを調整する – やらないとアウトラインがボケてしまう

Slide 84

Slide 84 text

Multi threaded Rendering $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 85

Slide 85 text

Multi threaded Rendering $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • CPUがGPUを待つケースが減り、FPSの上昇が 期待できる • (空いてるCPUコア数が少ないと意味はない)

Slide 86

Slide 86 text

Multi threaded Rendering $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • なのですが。。。 – UnityのMultiThreaded Renderingに関する資料は 少ない – マルチスレッド関係は不具合出やすい個所なので 注意しましょう。 • Multithreaded + DynamicBatchでハングする事例あり • Unity5.0.2p3で発生

Slide 87

Slide 87 text

指針と手法の答え合わせ $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE

Slide 88

Slide 88 text

大事なこと $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 端末の性能を把握する • コンテンツの要素を把握する – 適切な単位で区切り – コストを把握し – そのコストを最適化する • 要素を選択できるようにする

Slide 89

Slide 89 text

端末の性能を把握する $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 実際に計測すること • Profiler – Unity Profiler – Frame Debugger – GPU Profiler • 各種サイト – 3DMARK – Unity Hardware Statistics

Slide 90

Slide 90 text

要素を適切な単位で区切る $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • ゲーム的かつ技術的な視点で区切る – キャラクタ/背景/エフェクト – 頂点数/テクスチャ/ボーン数 – シェーダー – ImageEffect – CPU/GPU

Slide 91

Slide 91 text

コストを把握 $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 実際に計測すること • Profiler – Unity Profiler – Drame Debugger – GPU Profiler • CPU/GPUどちらがネックなのか • GPUネックならこれが参考になります • Computer Graphics Gems JP 2015 • http://www.borndigital.co.jp/book/5498.html# • 2.5.4 パイプラインのボトルネック解析

Slide 92

Slide 92 text

コストを最適化する $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 定期的に監視すること – できるだけ早いタイミングから – 想定された端末でのチェック – 機能が入ると知らない間にコスト上がる • 配分を決めること • FPS/SetPassといった性能指針を

Slide 93

Slide 93 text

要素を選択する $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • What if – ○○したらどうなるだろう • キャラクタを増やすor減らす • ImageEffectをOn/Offする • シェーダーを切り替える • 選択を容易にする機能を実装する • ゲームと独立した場所があるとベスト

Slide 94

Slide 94 text

おしまいです $POGJEFOUJBM $PQZSJHIU ˜$ZHBNFT *OD "MM3JHIUT3FTFSWFE • 時間があればDEMO