【初心者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で決定することができます。

 

結論、大事なこと

余計な衝突はしない!

スポンサードリンク