【初心者Tips】UnityVRの物理が重い!→原因を調査して判明した話
スポンサードリンク
こんにちは。ふぁんたです。
今回は、VRのホラーゲーム制作の話です。
学校を舞台にしたホラーゲームで、1クラスだけしっかり作り込んで、そこでいろいろな「人を驚かせるためのオブジェクト」が正しく動作するかどうか試してました。
そのオブジェクトたちが10個ちょっとになったので、そろそろ学校のクラスを全部完成させよう!と思ったところで、事件が起こりました。
ゲームが重い。
画面や手持ちの懐中電灯の動きがカクカクとし始め、動きと音が合わなくなり、ドアの動きもゆっくりとしたものに。
VRゲームって、視覚を全部覆っちゃうので、位置ずれとかFPS低下が致命的なんですよね。最悪酔う。
今回は、それに出会ってから重さを解消するまでやったことを説明します。
関連ワードは、
Unity,VR,UnityVR,Profiler,physics,fixedupdate,physicsfixedupdate,processing,portIslandGen,Rigidbody,collider,triggerあたりでしょうか。(検索用)
Contents
背景
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で決定することができます。
結論、大事なこと
余計な衝突はしない!
スポンサードリンク
ディスカッション
コメント一覧
まだ、コメントがありません