スクールシミュレータ開発の続きです。中古のPixel3を買って動作検証しましたが、
ちょっとマップに凝ったら11-17fpsまで落ちてしまって、まだNPCを歩かせてもないうちにこれはまずいと、設計を見直してました。
![](https://static.wixstatic.com/media/10f02c_79504f1c6b8747368f09d52ab1c97677~mv2.jpg/v1/fill/w_980,h_613,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/10f02c_79504f1c6b8747368f09d52ab1c97677~mv2.jpg)
ちなみにカクつくのはAndroidだけです。iPhone7は常時30fpsサクサク。
それでもPixel3はかなり高スペックな部類のはずなのですが、あまりに差があるのが納得いかなくて…
そしたら、うちの記事を読んだとあるインディーゲーム開発者さんから製作話を聞きましたが、うちの10倍以上のマテリアル数オブジェクト数のあるマップがサクサク動かせてたようなので、
自分の作り方が悪手だった可能性が出てきました。
色々わかったことを書き留めます。
1.POLARISテレインの木や草の本数を減らす
流石にモバイルでは植える本数に限度があったようで、調子に乗って植えすぎたのを減らしたらfpsが改善しました。
特に、草木にアルファテクスチャを使わないと露骨に改善しました。アルファをいっぱい使うビルボード表示を使うと、モバイルでは遅くなります。
2.草を表示しない
POLARISは木と草は別系統でレンダリングしてますが、草の方を非表示にすると大きく改善しました。
3.オクルーションカリングを使わない
シーン中の全オブジェクトに対して「物陰に隠れてるか」の判定を行うこの機能は、モバイルには重い処理で、かえって遅くなりました。
しかし、なければないで無駄にすべてをレンダリングしてしまうから、早くはなりません。
じゃあどうすんだよっていうと、後述
4.オブジェクトを減らすか非アクティブにする
オブジェクトを亡き者にすれば、ものによっては著しく効きます。逆に全く効かない場合もあります。
その過程で気づいたのが、POLARISテレインは、テレインと草木しか画面に映ってない状態だと爆速になる、ということでした。
建物とテレインの草木が画面に混在すると途端にカクつきました。
ということで建物と森林を離して、町中の木はテレインのものでなく、プレハブの木で表現すると改善されました。しかしそれでも、町と森林の境目は解決しきれませんが。
5.影をオフにする、AAポストエフェクトを切る、カメラカリング距離を下げる、etc
このへんは語るまでもないことなので省略しますが、一つだけ
カメラの距離描画制限は、レイヤー別に設定できます。
![](https://static.wixstatic.com/media/10f02c_8b08925cdfbc4fc3a56486041358d397~mv2.jpg/v1/fill/w_482,h_820,al_c,q_85,enc_auto/10f02c_8b08925cdfbc4fc3a56486041358d397~mv2.jpg)
カメラの隠し機能で、スクリプトでないとできません。
これでキャラやショップの小物とかは距離を短く、灯台など遠くから見えてほしいものは距離を長く、と個別に設定できます
6.URPをやめる
モバイルでテレインを実現するPOLARISや数千数万の同一オブジェクトの処理を軽くするGPUInstancerは、URP対応とは言ってるものの、使用時に悪い影響が出てるレビューも見かけました。
前作のゲームではLWRP・URPは導入したら露骨に早くなったので今回も導入したのですが、
URPは、GPUを酷使することで画質を上げてレンダリング速度も上げる仕様のようなので、同じGPU(やCPUマルチスレッド)を酷使する系アセットとの併用はまずいのでは、と思い当たりました。
ということでURPをアンインストールしますと…
※インポートした数々のアセットをURPから戻すには、アセットをインポートしなおし、上書きで初期化する必要があり(しかもインポート上書きしようと思ったら、アセットのアップデートが来てしまってもとに戻せなくなった)、この検証はちょっとリスキーです。プロジェクトをバックアップしてから試します
20-30FPSいく部分が明らかに増えてました。
くわえて、URPではド汚くなるシャドウが実にきれいに出ます。
URPやHDRPだと、シャドウのオンオフ、AAなどのグラフィックオプションの実装の難易度が跳ね上がるんですよね…
でもURPはビル窓の映り込みと水の綺麗さが強い。どちらか犠牲にしないといけません。
処理速度上がる系アセットは全て、それ以外の処理速度上がる系アセットおよび、URP/HDRPと、競合する可能性があるといっていいのではと思いました。
アセットの説明にDOTS/JOBS/BURSTとかの文字が見えたら用心しましょう。
導入前にアセットのマニュアルやフォーラムを読むと、そのあたりの仕様が明らかになるかもしれません。開発者に問えば改善してくれるかもしれません。
7.メッシュ統合を控える
メッシュベイカーで細かい塀などを統合して、ビルも1区画ごとに統合して、オブジェクト数は3000個を下回りましたが、
予想に反してかえって遅くなりました。
統合した建物や道路が画面に初めて映る時などで、超カクつきました。
統合したメッシュは巨大なユニークメッシュだから、プレハブインスタンスの恩恵は受けられなくなる、データをメモリに展開するのにシャレにならない時間がかかるとか、そんな理屈でしょうか?
統合するべきは道路や柵のような大量にある同じプレハブでなく、シーン中一つ2つしかないユニーク建物同士が効果的なのでしょうか。
それとも面積が問題でしょうか?デカければ同時に画面に映りやすくなってしまう。
重い建物は一度に画面に映らないよう離して配置するのが有効と聞きましたので、そういう事考えたメッシュ統合とレベルデザインが必要です。
8.テクスチャを可能な限り小さくするか使わないで、その分マテリアルをたくさん使う(未検証)
アセットストアによくあるテクスチャ皆無の生ポリゴンなローポリモデル、
あれは、単色のモバイル用マテリアルが大量に使われても、全くメモリやレンダーを圧迫しないみたいです。
Androidで遅くてiPhoneで安定してサクサクという差が出た原因は、私のモデリング技法が原因かもしれません。
カモメ町は可能な限り少ないアトラスにテクスチャをつめこんで、マテリアル数を非常に少なく作りましたが、
![](https://static.wixstatic.com/media/10f02c_8e4f70fcb87047e5b099c575e1d3a3fd~mv2.jpg/v1/fill/w_273,h_261,al_c,q_80,enc_auto/10f02c_8e4f70fcb87047e5b099c575e1d3a3fd~mv2.jpg)
昔どこかで見た情報(ソースは失念)で、
「大きいアトラスで枚数が少ないテクスチャはiPhoneに優しい仕様で、Androidが喜ぶのは小さいテクスチャを大量に使う仕様」、というのを思い出しました。
その話が本当なら、私の作り方がiPhoneに最適化されすぎだったのかもしれません。
マテリアルとテクスチャの数減らしを最優先せず、タイルテクスチャで表現できる部分をできるだけ見つけて選り分けて、それ以外をテクスチャ一枚あたり4-9種類程度にまとめたテクスチャパッキングにするのが、iPhoneでもAndroidでもつぶしがきく賢い作り方、ということなんでしょうか。
iPhoneとAndroidで差がありすぎるのでそんな考えがよぎりました。実証はできない。
マテリアルカラー頂点カラーが重いだのマテリアル数を減らすのがジャスティスだの、それは偏った古い情報で、今では逆ってこともあるかもしれません。
(そもそもプログラマーのいう「重い処理」が、使えば即FPSが一桁になるのか、アプリが吹っ飛ぶものか、数十万回処理したら数フレームの遅延が出る程度かでは話が違いすぎるのに、ひとまとめに「重い」とする記事が多いです)
9.自前のカリングを施す
Unity自前のオクルーションカリングはモバイルには重くて使えないけど、ステージのカリング自体はド必須です。
これも人から聞いたテクです。室内や山の向こう側など、プレイヤーのいる位置から確実に見えなくなる場所のオブジェクトは非アクティブにする切り替え処理を実装すれば、処理負荷は大きく改善するでしょう。
![](https://static.wixstatic.com/media/10f02c_5b46aaa136fb49a5837fd20f24458371~mv2.jpg/v1/fill/w_932,h_574,al_c,q_85,enc_auto/10f02c_5b46aaa136fb49a5837fd20f24458371~mv2.jpg)
ステージを包む複数のトリガーコライダーとステージオブジェクトのリストを登録して、プレイヤー+カメラが入ったエリアごとにステージオブジェクトの表示非表示を切り替える。
![](https://static.wixstatic.com/media/10f02c_888c97c5fed74dd0be4f7c99bfe3ca18~mv2.jpg/v1/fill/w_486,h_739,al_c,q_80,enc_auto/10f02c_888c97c5fed74dd0be4f7c99bfe3ca18~mv2.jpg)
コードはトリガーを作動させるイベントと、配列と、SetActive()を使うだけで作れます。
ただし、実装の難易度は、レベルデザイン次第です。
ぐにゃぐにゃした地形は当然コライダーの配置が面倒です。建物が一切映らない空白地帯があると最高。
カメラ複数使うゲームシステムやワープ移動には、また工夫が必要です…
これは効果は最も大きかったです。20フレーム以下に下がらず、30fps出る部分が多くなりました。
ただし画面外で動くキャラにとっては、足場がなくなるので動作に支障が出ます。
キャラごとカリング=非アクティブにする、プレイヤーが見てるときしか行動しない、
そうしても不具合が出ない設計にする、必要があります。
コメント