【初心者Tips】UnityVRの物理が重い!→原因を調査して判明した話

スポンサードリンク

こんにちは。ふぁんたです。



今回は、VRのホラーゲーム制作の話です。



学校を舞台にしたホラーゲームで、1クラスだけしっかり作り込んで、そこでいろいろな「人を驚かせるためのオブジェクト」が正しく動作するかどうか試してました。



そのオブジェクトたちが10個ちょっとになったので、そろそろ学校のクラスを全部完成させよう!と思ったところで、事件が起こりました。





ゲームが重い。





画面や手持ちの懐中電灯の動きがカクカクとし始め、動きと音が合わなくなり、ドアの動きもゆっくりとしたものに。







VRゲームって、視覚を全部覆っちゃうので、位置ずれとかFPS低下が致命的なんですよね。最悪酔う。





今回は、それに出会ってから重さを解消するまでやったことを説明します。



関連ワードは、

Unity,VR,UnityVR,Profiler,physics,fixedupdate,physicsfixedupdate,processing,portIslandGen,Rigidbody,collider,triggerあたりでしょうか。(検索用)




背景


6クラスある学校を使ってホラーゲーム。



1クラスだけ作り込んで、動作チェック。



いい感じに出来上がってきたので、完成した部屋をコピペで増やす。



すると、なんだか重い。カクカクする。


目的


ゲームの機能を削らないように、軽くする。



めざせ60FPS。




したことの流れ


まず、なんで重いのか知りたい。



わからない。



早速五里霧中ですが、こんなときに使える、何が重いのかを教えてくれる機能がUnityには備わっています。



Profilerです。


(Windows→Analysis→Profilerから開けます)

(Ctrl+7でも開けるみたいです)





開いた状態で、ゲームをプレビュー[再生ボタン]すると、処理にかかっている時間などを詳しく見ることができます。







下画面は置いといて、とりあえず上画面を見ます。





左に凡例があり、右にグラフ。

横向きの線は、処理の結果によるFPS(ゲーム処理の快適さ)を表しています。





今回、とってもオレンジです。



凡例を見ると、「Physics(物理)」がオレンジで大変な計算量をしていることがわかります。





こいつを減らすことが今回の目標です。


詳細を見てみる


じゃあなんでこのオレンジが大きくなってるのか、詳細を見てみましょう。



下画面を見ます。



下にある、「Hierarchy」のTime ms順に並べ替えましょう。



悪いことしてる順になります。





そのHierarchyの各行をクリックすると、上のグラフのどれに属するのかをハイライトして教えてくれます。





この例だと、FixedUpdate(毎フレームごとに呼ばれる)の、PhysicsFixedUpdate(なんかしらんけど物理)が最も悪いことしてるやつ、ということになります。





もっと詳しいことが知りたい場合は、上画面にある、[Deep Profile]というボタンをクリックするとよいです。



自分の場合、それを押したら、physX.ScScene.portIslandGenというものが諸悪の根源でしたが、これが一体何をしているのかについては、ググっても全く出てきませんでした。



ということはこの情報については今ここが最前線だ。




本当になにをしていいかわからなくなった




とりあえず、物理が悪さをしている、という事はわかりました。

でも、これ以上のことはよくわかりません。





幸いにも、Unityには「プレビュー再生中に行った変更は、プレビュー後全部もとに戻る」という性質があるので、一つ一つ消していって試すことができます。







試行錯誤の結果、いろいろとわかったので、やったことと結果を書きます。





・教室がある側を見ると、重くなる。ない側を見ると軽くなる。

もしかして見えてない部分も描画されて重い





・教室がある側を見て、教室を全部消すと軽い。

教室が原因っぽい。





・6つある教室のうち、5つを消してみると軽い。

教室が複数あるのが原因っぽい





・机を消しても重い、椅子を消しても重い

→机と椅子が衝突しまくってるわけではなさそう





・教室のものを単独で一つずつ消して出す。でも重い。

教室内の一つのアイテムが原因ではない







わからん。ほんとにわからん。



さっぱりわからんので、基本に立ち返ってみました。


Colliderを見直す


そもそも、Colliderって何のためにあったんでしょう(基本)

Rigidbodyとごっちゃになって、ぶつかる挙動をするものには適当につけていた思い出があります。





振り返りましょう。



Colliderは、「衝突を検知するコンポーネント」です。

ぶつかる(Collision)のも、ぶつかったけど通り抜ける(Trigger)のもこいつです。

衝突をさせる場合、ぶつかる方かぶつかられる方に、Rigidbodyをつけます。





Colliderにも、いろいろ種類があります。



箱の形のBoxCollider、球の形のSphereCollider、カプセルのCapsuleColliderなどです。

教室の形はどれでもないので、3DモデルからColliderの形状を作り出す「Mesh Collider」を使って当たり判定を生み出しております。



このMeshColliderが重かったので、なるべく上に挙げたような別のColliderを使うほうが良いです。



こういう表記を見つけたので、MeshColliderをいくつか変えました。

パフォーマンスは、変わりませんでした。


Rigidbodyを見直す




じゃあ、Rigidbodyは何なのでしょう。(基本)

これは、「物理演算するためのコンポーネント」です。

動いてほしいものにつけます。





衝突のときはColliderなのですが、片方が動いてないと物は衝突しないので、必ずどちらかにつけないといけません。

今回のゲームでは、自分が歩いて机は動かないので、Rigidbodyは自分に、Colliderは自分と机の両方につける必要があります。



Rigidbodyが多いと、それだけ物理演算が必要になります。

なので、無駄につけないようにしましょう。

つけなければ、物体は動くことはありません。



でも、これを変えても、自分のゲームのパフォーマンスは変わりませんでした。


結局、明らかになった原因




なにか、ものすごくたくさんの衝突が起こっているのでは?と思い、試行錯誤を繰り返しました。









結果、悪いやつがわかりました。



こいつです。



目線を取得するためにつけた目線Colliderが、教室内のいろいろなものと衝突し、都度衝突計算が走っていたようです。





衝突計算を回避する方法ですが、

「衝突のレイヤー分け」という方法があるので使いました。

衝突のレイヤー分け


Edit→Project Settings→Physics を選択します。



開いたら、レイヤーごとに衝突するかのマトリックスが表示されます。

衝突行列

ここで、レイヤーごとに衝突を行うか、行わないかを決定することができます。



どのオブジェクトをどのレイヤーに割り当てるかは、



ゲームオブジェクトのLayerで決定することができます。


結論、大事なこと


余計な衝突はしない!

スポンサードリンク