Oculus Rift用に開発した「DINOTOWN」というコンテンツがあります。

街中を恐竜が歩き回っており、ユーザーはOculus Riftを装着してその街中を歩き回る体験できるというコンテンツになっておりますが、Oculus Riftで開発したこのコンテンツを「スマホでも体験できるように」という無謀な遣り甲斐のある!企画があがりました。

Oculus RiftはもちろんデスクトップPCで動く事を想定してコンテンツを制作していたため、スマホ版へ移植するにあたってはいくつか問題点が浮上しましたが、その中でも「高速化」ということが一番の課題でした。

DrawCallを極力減らしスマホ版でもヌルヌル動くコンテンツを目指し色々試行錯誤しながら行った事をご紹介いたします。

DINOTOWNキャプチャ

まずはじめに…


何も考えずにAndroidやiOSにプラットフォームを切り替えてビルド

  • メモリ不足で起動しないかも、と懸念したが意外と普通に起動できた
  • だがフレームレートは当然ひどい有様…
  • DrawCallが1000近くもあったため、当然といえば当然

目標を設定

  • 最終的にフレームレートの目標を30FPSに設定
  • 対応端末はiOSではiPhone5以上、Androidはここ一年以内くらいに発売された端末をターゲット

DrawCallを減らす!


操作方法の変更

  • Oculus Rift版ではゲームコントローラーを使用して、ユーザーが街中の任意の場所に移動が可能
  • スマホ版ではゲームコントローラーが使用できない
  • なのでスマホ版では自動運行で街中を移動するように対応
  • それに伴い、コンテンツの体験に影響のないオブジェクトを削除してDrawCallをかせぐ

これは当然効果がありました!

Before オブジェクトを削除する前

After オブジェクトを削除した後

動かないオブジェクトへの対応

  • 動かない(移動、回転、拡大縮小)表示物のオブジェクトに対してはstaticにチェックを入れる ※Unity Pro版を使用していると、Static Batching機能によりメッシュ結合されるため高速化が期待できる

これも割と効果があります!

Static

圧縮テクスチャ設定

  • 以前、iOSの開発でOpenGLで圧縮テクスチャを使用した場合とそうでない場合でフレームレートに差が出た (圧縮テクスチャを使用した方が早くなった)
  • UnityではiOSはデフォルトで圧縮テクスチャを使用する設定になっているが、Androidでは設定されていないためAndroidを圧縮テクスチャ設定
  • ただし見た目が極端に悪くなってしまう場合は圧縮設定しない
  • 今回の場合だとSkyBoxに使用しているテクスチャを圧縮したら極端に見た目が悪くなったため、このテクスチャだけは圧縮しないように設定

これについては、Android版では高速化に関してあまり効果が見られませんでした… (iOS版ではデフォルトで圧縮テクスチャ設定が行われているため未確認)

CompressedTexture

シェーダーの設定

  • Mobile用のシェーダーの設定 ※Unityはモバイルプラットフォーム向けのシンプルなシェーダーを提供している

使用している表示物のシェーダーを可能な限りモバイル用に設定してみましたが、あまり高速化の効果は見られませんでした…

Shader

クオリティの設定

  • Qualityの設定である程度見た目を犠牲にして高速化を目指す
  • Unityのメニューの Edit > Project Settings > Quality
  • QualityのレベルはFastestに設定
  • Texture QualityHalf Res
  • Anisotropic Textures(異方性テクスチャ)はDisabled
  • Anti AliasingDisabled
  • ShadowsHard Shadows Onlyにし、Shadow ResolutionMediumに設定

結構速くなりました! どうやら動的シャドウに負荷が結構かかる模様。 試しにShadowsDisable Shadowsにしたところだいぶ速くなったのですが、「影はやっぱりあった方がよい」という意見があったため、無効にせずほかの方法を検討しました。

QualitySettings

ここまでの設定で…

  • 以上の設定を行っても、30FPSにはちょっと足りない! カメラが見る箇所によってはDrawCallが500近くに…

マテリアル、テクスチャを統一してStatic Batching

  • 街中のビルや電話ボックスなど、可能な限り同一のマテリアルを使用させるように設定する
  • ビルや電話ボックスなどのテクスチャをひとつにまとめる
  • テクスチャをひとつにまとめたので当然テクスチャ座標の修正が必要 → 3Dモデリングツールを使用してテクスチャ座標を修正 今回は私(プログラマー)がMayaLTの体験版を使用してチャレンジ! その詳細は、記事 : 「MayaLT で DrawCall を可能な限り減らす」をご覧ください。
  • マテリアルやモデルによっては対応できないものもあり(ケースバイケース)

上記の対応によってDrawCallが約1/3に減少!

結果として…

  • iOS版ではiPhone5でも30FPSを維持できるようになった
  • Android版はまだちょっと遅い感じ

(やむなしの対応として)Rendering Pathの変更

  • Unityのメニューの Edit > Project Settings > Player
  • 元々Oculus Rift版ではForward Renderingのコンテンツ
  • Forward Renderingはピクセル単位でのライティング処理のため、スマホ版では負荷がかかる
  • iOS版ではForward Renderingのまま、Android版はVertex Litに変更
  • Vertex Litは頂点単位でのライティングのため、スマホでのコンテンツでは推奨される
  • 街中のモデルはライトマップが適用されているため、Vertex Litにしても見た目に変化はなし
  • ただしVertex Litは動的シャドウをサポートしていないため、Android版では恐竜の影はなし

上記対応でついにAndroid版でも30FPSを維持できるようになりました!!

RenderingPath

アプリ公開へ!

「DINO TOWN for SmartPhone」が以下より無料でダウンロードできます。是非、体験してみてください!

まとめ


今回はPC版からスマホ版への移植を行うにあたり、試行錯誤を重ねながら高速化を行いました。 この記事が実装にあたっての参考になれば幸いです。