Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Unity+スマホで3Dゲーム開発最適化するための考え方
Search
Cygames
January 14, 2016
Programming
15
25k
Unity+スマホで3Dゲーム開発最適化するための考え方
2015/11/15 Cygames Tech Fes
Cygames
January 14, 2016
Tweet
Share
More Decks by Cygames
See All by Cygames
最高のアートワークを発信する『Cygames展 Artworks』企画制作事例
cygames
0
60
社内にバーチャルスタッフ!?「スイちゃん」のキャラクターデザインと施策の広げ方の秘訣
cygames
1
170
全高3m超のバハムート像がスマホを通して躍動する! ~『Cygames展 Artworks』ARコンテンツの開発プロセスと実装~
cygames
0
53
最高の資料を目指すために!社内フリーイラスト制作チームの取り組みについて
cygames
1
170
「生きているモーション」を作り出すCygamesのモーションキャプチャー
cygames
0
120
『Cygames展 Artworks』におけるShadowverseデジタルサイネージ制作事例
cygames
0
49
『GRANBLUE FANTASY: Relink』 原作の世界観に没入するステージの絵作り
cygames
0
1.2k
『GRANBLUE FANTASY: Relink』イラストを再現する為のキャラクターモデル制作事例
cygames
0
190
『GRANBLUE FANTASY: Relink』キャラクターの魅力を支えるリグ制作事例
cygames
0
120
Other Decks in Programming
See All in Programming
Denoでフロントエンド開発 2025年春版 / Frontend Development with Deno (Spring 2025)
petamoriken
1
1.3k
Preact、HooksとSignalsの両立 / Preact: Harmonizing Hooks and Signals
ssssota
1
960
海外のアプリで見かけたかっこいいTransitionを真似てみる
shogotakasaki
1
130
ベクトル検索システムの気持ち
monochromegane
30
9.4k
snacks.nvim内のセットアップ不要なプラグインを紹介 / introduce_snacks_nvim
uhooi
0
360
ノーコードツールの裏側につきまとう「20分岐」との戦い
oguemon
0
110
Productivity is Messing Around and Having Fun
hollycummins
0
150
アーキテクトと美学 / Architecture and Aesthetics
nrslib
12
3.2k
新卒から4年間、20年もののWebサービスと 向き合って学んだソフトウェア考古学
oguri
8
7k
Defying Front-End Inertia: Inertia.js on Rails
skryukov
0
340
DataStoreをテストする
mkeeda
0
210
remix + cloudflare workers (DO) docker上でいい感じに開発する
yoshidatomoaki
0
120
Featured
See All Featured
The Cost Of JavaScript in 2023
addyosmani
48
7.6k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
GraphQLとの向き合い方2022年版
quramy
45
14k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
60k
Agile that works and the tools we love
rasmusluckow
328
21k
Become a Pro
speakerdeck
PRO
27
5.2k
Site-Speed That Sticks
csswizardry
4
460
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
How to Think Like a Performance Engineer
csswizardry
22
1.5k
Git: the NoSQL Database
bkeepers
PRO
429
65k
Raft: Consensus for Rubyists
vanstee
137
6.9k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
22
2.6k
Transcript
Unity+スマホで3Dゲーム開発/最適化 するための考え方 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE 株式会社Cygames エンジニア
金井 大
自己紹介 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 金井 大
• 技術研究チーム所属のエンジニアです • VR、ゲームエンジン、グラフィックスとかの研究 開発してます
アジェンダ $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • Unity +
スマホで3Dゲーム開発/最適化する ための考え方を、以下で紹介します – 開発の指針 – 構成およびスペックの一例 – 開発と最適化のためのTIPS – 指針と手法の答え合わせ
開発の指針 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
大事なこと $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 端末の性能を把握する •
コンテンツの要素を把握する – 適切な単位で区切り – コストを把握し – そのコストを最適化する • 要素を選択できるようにする
UNITY HARDWARE STATISTICS $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE •
出典:http://hwstats.unity3d.com/mobile/ • unity mobile stat で検索
詳細 $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%
3DMARK $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 出典:http://www.futuremark.com/hardware/mobile/ •
3DMARK mobile results で検索
3DMARK $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 拡大
どうしてこうなった $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • キャリア •
チップセット • CPU – コア数 – クロック • GPU • メモリ
PCゲームのグラフィックス設定 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 出典: http://doope.jp/media/15q1/img2826_01.j
pg
$POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • どこまでユーザーに選択させるか?
スマホでの現実解は? $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • ある程度は大まかに制御したい –
エフェクト ON/OFF – 効果音 ON/OFF – FPS – スペックの抽象化
$POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 「スペックの抽象化」ってなんやねん
例えばシェーダーを例に $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • Vertex shader
– カラーアニメーション – UVアニメーション – アウトラインメッシュの法線方向への拡大 – セルルック • Fragment shader – イメージエフェクト – スキンシェーダー – ノーマルマップ – セルルック
アプリケーションでの抽象化 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • Vertex shader
– カラーアニメーション – UVアニメーション – アウトラインメッシュ – セルルック • Fragment shader – イメージエフェクト – スキンシェーダー – ノーマルマップ – セルルック 低スペック 高スペック 使わない
端末に落とし込む $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • Vertex shader
– カラーアニメーション – UVアニメーション – アウトラインメッシュ – セルルック • Fragment shader – イメージエフェクト – スキンシェーダー – ノーマルマップ – セルルック 低スペック 高スペック 使わない iPhone5s iPhone6 iPhone6s Galaxy S5 Galaxy S6
大事なこと $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 端末の性能を把握する •
コンテンツの要素を把握する – 適切な単位で区切り – コストを把握し – そのコストを最適化する • 要素を選択できるようにする
構成およびスペックの一例 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
目標 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 60fpsをキープしたい •
キャラクターを5体表示 • 絵力 – フェイシャル – モーションキャプチャー – 他と差別された強い絵力が欲しい! • タイトなスケジュールに負けない
より現実的なゴール $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 低スペック端末では –
幅広く動作するようクオリティぎりぎりまでスペック を落としつつ60fpsをキープ • 高スペック端末では – 高性能端末で高品質な画面を提供しつつ60fpsを キープ
キャラクター $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • スペック –
テクスチャ • ETC1(αチャンネルなし)/PVR • Mipmapなし(データサイズ縮小のため – ウェイト • 基本は2ボーン – 3ボーンをPlayerSettingで2にするとメッシュが崩れることがあ る
キャラクター $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • フェイシャル –
ボーン制御 – Animatorで眼球、リップの動きを用意し、外部から 制御 – 眼球の追従先をプログラム制御 • アウトライン – アウトラインメッシュ – 頂点カラーでの調整 – リムライト、セルルックは…? • 造形が良ければアウトラインでも
キャラクター $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • クロス –
独自実装 – それなりに重いので、まずはC#でチューン • 計算部分のみなら22行程 – マルチスレッド化できるようにデータ局所化 – あとはネイティブプラグイン化すれば…
背景 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • テクスチャ –
基本はETC1(αチャンネルなし)/PVR – Mipmapあり – UVアニメーション用に3MB程度を確保 • 画面キャプチャ – ImageEffectで作成した中間バッファを流用 – 1フレーム遅れた絵になるが低コスト
その他 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • ライティング –
基本的にはライティングしない – アンビエント – 板を1軸回転してカメラに向けてボリュームライトっぽく • シャドウ – リアルタイムシャドウは断念 – 板ポリの安いやつ。Diffuseに焼く。 • ないと立体感なくなります • パーティクル – 一定数まとまったメッシュを用意 – パーティクルとして降らせる – Vertex shaderで動きをつける
Image Effect $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • ImageEffect
– DOF(被写界深度 – Bloom – カラーコレクトはオミット • Unityのシェーダーをベースに – 1カメラで実現できるようカスタマイズ – ついでに高速化
Directシーン $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • キャラクターや背景の任意組み合わせを確認でき る専用シーン
• デザイナー/プランナーの作業、確認が主用途 • 各種アセットのデータ形式に対応 – 通常アセット – アセットバンドル(サーバー上 – アセットバンドル(ローカルPCにつくったやつ • 端末でも動作可能 – アプリ本体を経由しないので、単体テストやコスト計測 にも使える
開発と最適化のTIPS $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
計測 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
Unity Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
Statistics $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
FrameDebugger $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • DrawCallを確認可能 –
Unity5から こ の へ ん が 描 画 リ ク エ ス ト
GPU Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 描画系の追跡はUnity
Profilerでは限界がある – オーバーヘッド – GPUのプロファイルに難アリ • チップセットと対になったGPU Profilerを使う – iOS -> instruments / OpenGL ES Frame Debugger – Adreno -> Adreno Profiler – Tegra -> PerfHUD ES • 端末や要素の性能を把握できる
例:Adreno Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
Adreno Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • プロファイルした情報を保存することが可能
– チューニング前後の比較に • 頂点データ/テクスチャの保存 • シェーダーの可視化と変更 • Etc…
Adreno Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • FrameDebuggerと同じくDrawCallが目視で
きる
Adreno Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • フレームバッファ、テクスチャのキャプチャ
• シェーダー修正
Adreno Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • FPSやGPU使用率などをグラフ化
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • おおざっぱに以下のように考える –
vertex負荷 = (描画リクエストされた頂点数) x (vertex shaderの命令数) – fragment負荷 = (描画されたピクセル数) x (fragment shaderの命令数) – 厳密にはパイプライン次第だと思う • 各ベンダー/各世代のチップ考慮するのは大変なので
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 出典: http://climserv.ipsl.polytechnique.fr/documentation/idl_he
lp/images/shader_detail.gif
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 例:球(4000頂点)を(1/1)と(1/4)で描画し た時の比較
– vertex負荷は同じ – fragment負荷は約1/16になる
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • vertex負荷の制御はデリケート –
描画対象となる頂点数を減らしたい – 何らかで頂点数を削れば良いのだが… • データ削減するとシルエット崩れや作業コストが懸念 • カリング精度を上げるにはCPU/GPU負荷が懸念 • fragment負荷は比較的制御しやすい – 描画面積とシェーダーで制御できる – カメラワークには注意
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • vertexは最初から低めに抑さえる –
特に低スペック端末を考えると低めにせざるを得 ない – 最低限のLODデータを用意する • fragment負荷を制御できる手段を用意する – ImageEffectをOn/Offする – 画面解像度を制御する – Meshのfragmentシェーダーを軽量版に切り替える
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
描画順の制御 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
描画順の制御 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 前提として「描画順」と「ZTest」を理解する –
ZTestが有効な場合、隠れたfragmentは描画されない • 1がZ値的に手前にある時、1を描いてから2を描 くと、一部は描画されない 2 1
描画順の制御 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 極端にすると。 •
1を描画してから2を描くと、2は殆ど描画されな い 2 1
隠れているのがポイント $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • アウトラインメッシュの描画が無駄になるので •
こういう順番にしたい
描画順の制御 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 不透明は(基本的には)手前から描く –
隠れた個所はfragmentシェーダーが走らない – 基本的にUnity側が手前からソートしてくれてる
描画順の制御 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • なんだけど –
原点位置を基準にソーティングする – 意図した結果になるとは限らない – こういう時は床を最後にしたいが原点基準だと。。。
描画順の制御 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • Unityで描画順を制御する手段 –
Camera.depth – MeshRenderer.sortingLayerName – MeshRenderer.sortingOrder – Material.renderQueue
描画順の制御 $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
Camera.depth $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • CameraはCullingMask設定が必要になるなど、 色々面倒
– ImageEffect使用時は注意! • Camera.clearFlags=Depthだとclearが劇重 • GPU20%程度の消費することも
MeshRenderer.sortingLayerName $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • sortingLayerNameは以下で追加可能 –
Layers -> Sorting Layers • 記載の順番に処理される
MeshRenderer.sortingOrder $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 同じsortingLayerNameでの描画順 •
sortingLayerNameと合わせて運用を考える
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」になる
こんな事も $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 「髪の毛より手前にある眉」
髪の毛より手前にある眉 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 髪の毛に隠れてしまう眉毛を何とかして手前 に出したい
– ZTest / ZWriteをOffにして対処 – ZTestしないので、「必ず」最前面に眉が描かれる (髪の上に描かれる) – ZWriteしないので、他のオブジェクトにZ値干渉し ない
髪の毛より手前にある眉 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 弊害として、他キャラの眉毛が貫通してくる可 能性がある
– 描画順を制御して奥から描く • キャラA頭 • キャラA眉 • キャラB頭 • キャラB眉 • …
髪の毛より手前にある眉 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 問題はいくつか残る –
頭と眉の形状によっては、自キャラの眉が貫通して くる • カメラワークでの回避 – 無駄な描画が発生する • 我慢する
SetPassとDrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
DrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • まずDrawCall –
GPUへ描画リクエストする、ということ – 固有のマテリアルを描画リクエストすると 1DrawCall消費する – Unity5からStatisticsより消失しました
$POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 「固有のマテリアルを描画リクエストするとDrawCall 消費する」ってなんやねん •
「固有のマテリアル」ってなんやねん
DrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 固有のマテリアルとは –
UnityEngine.Materialのメンバがユニークであるこ と – 例えば • Colorが異なる • Textureが異なる • Shaderが異なる • Etc… – 他と異なるメンバがあれば、それは固有である
DrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • BOX全体にマテリアルA →
DrawCall=1 • BOX各面にマテリアルABC → DrawCall=3 A A B C
DrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX全体にマテリアルA)x2 →
DrawCall=2 • (BOX各面にマテリアルABC)x2 → DrawCall=6 A A B C A A B C
DrawCallとバッチ処理 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 同じマテリアルだったら最適化できそう •
そこでバッチ処理 • 同じマテリアルをもつドローコールを統合する
DrawCallとバッチ処理 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX全体にマテリアルA)x2 →
DrawCall=1 A A
DrawCallとバッチ処理 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX各面にマテリアルABC)x2 →DrawCall
数は描画順に依存する(後述) A B C A B C
DrawCallとバッチ処理 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • バッチ処理は2種類ある •
StaticBatch – 移動しない同一マテリアルを持つメッシュをマーキングし、 事前にバッチ用のデータをしこむ – 統合の効果が高いが、移動したりマテリアル操作するメッ シュには適応できない • DynamicBatch – 前後のドローコールが同一マテリアルをもつ場合、ランタイ ム時に統合する – ランタイムに行うのでCPUコストがそこそこある – StaticBatchより効果が低い(頂点数等の制限数がある) • http://docs.unity3d.com/ja/current/Manual/DrawCallBatchin g.html
DynamicBatch $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • DynamicBatchの注意点 –
前後のドローコールが同一マテリアルを持たないと統 合しない – 描画順によっては統合できない! – 例えば描画順が以下だと統合されない • BOX(マテリアルA • BOX(マテリアルB • BOX(マテリアルC • BOX(マテリアルA • BOX(マテリアルB • BOX(マテリアルC • DrawCall=6になる
DynamicBatch $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 描画順が以下であれば統合される –
BOX(マテリアルA – BOX(マテリアルA – BOX(マテリアルB – BOX(マテリアルB – BOX(マテリアルC – BOX(マテリアルC – DrawCall=3になる • 描画順は前述のsortingOrderで制御可能
DrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • DrawCallを減らすのであれば、描画時に固有 マテリアルが連続するよう、ルールを決めてお
く – Batch処理を利用する – sortingOrder等で描画順を制御する – そもそも固有マテリアルを減らす • テクスチャを共有化する • シェーダーを共有化する • 変更するパラメーターを限定する • Etc…
SetPass $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • SetPassとは –
よりパフォーマンスの指針となる数値 – DrawCall時に前回使用したマテリアルから変更が あった場合、1SetPass消費する
SetPassとDrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 【Unity】Unity Performance
Casual Talk 「ド ローコール伝説の終わり」 レポート – http://qiita.com/baba_s/items/5260807ced7fc3c02ca 6
SetPassとDrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX全体にマテリアルA)x2 →
SetPass=1 • バッチに依存せず、SetPassは1になる A A
SetPassとDrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX各面にマテリアルABC)x2 →
SetPassは描 画順に依存する • SetPassを減らすにはDrawCallと同じく描画順を 意識する • DrawCallと同じノウハウが利用できる A B C A B C
Depth Texture $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
Depth Texture $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • ImageEffectの被写界深度はZ値を参照してボカ
シ処理を行う • Z値を参照するには、DepthTextureが必要 – Camera.depthTextureMode = DepthTextureMode.Depth; • 注意点 – DepthTextureはRenderTargetへ描画を行うことで 生成されてる – DepthTextureへポリゴンを描いている、ということ – 単純に描画頂点数が二倍になる
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で変更された箇所なので注意
Depth Texture $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • ShadowCasterシェーダーを実装する理由
– アウトライン+DOF時に必要となる事がある – キャラクターはアウトライン分微妙にサイズが大き くなる • ので、DepthBufferに書き込む大きさを調整する – やらないとアウトラインがボケてしまう
Multi threaded Rendering $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
Multi threaded Rendering $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE •
CPUがGPUを待つケースが減り、FPSの上昇が 期待できる • (空いてるCPUコア数が少ないと意味はない)
Multi threaded Rendering $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE •
なのですが。。。 – UnityのMultiThreaded Renderingに関する資料は 少ない – マルチスレッド関係は不具合出やすい個所なので 注意しましょう。 • Multithreaded + DynamicBatchでハングする事例あり • Unity5.0.2p3で発生
指針と手法の答え合わせ $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
大事なこと $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 端末の性能を把握する •
コンテンツの要素を把握する – 適切な単位で区切り – コストを把握し – そのコストを最適化する • 要素を選択できるようにする
端末の性能を把握する $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 実際に計測すること •
Profiler – Unity Profiler – Frame Debugger – GPU Profiler • 各種サイト – 3DMARK – Unity Hardware Statistics
要素を適切な単位で区切る $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • ゲーム的かつ技術的な視点で区切る –
キャラクタ/背景/エフェクト – 頂点数/テクスチャ/ボーン数 – シェーダー – ImageEffect – CPU/GPU
コストを把握 $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 パイプラインのボトルネック解析
コストを最適化する $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 定期的に監視すること –
できるだけ早いタイミングから – 想定された端末でのチェック – 機能が入ると知らない間にコスト上がる • 配分を決めること • FPS/SetPassといった性能指針を
要素を選択する $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • What if
– ◦◦したらどうなるだろう • キャラクタを増やすor減らす • ImageEffectをOn/Offする • シェーダーを切り替える • 選択を容易にする機能を実装する • ゲームと独立した場所があるとベスト
おしまいです $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 時間があればDEMO