Upload
masanori-nishio
View
8.001
Download
0
Embed Size (px)
Citation preview
Unity物理におまかせゴルフ〜ぐるぐるイーグル〜
株式会社 Aimingソフトウェアエンジニア
西尾 昌哲
このスライドの概要
Unity4の物理エンジンを利用してゴルフゲームを作ってみた結果、得られた経験
・物理オブジェクトの構成や設定周り ・物理エンジンにまかせっきりにできたこと ・特殊な制御しなければできなかったことなどを紹介
・ゴルフゲームを構成する物理オブジェクト ・ゴルフボールの挙動について ・パフォーマンスについて ・デバッグについて ・物理エンジンを使ってみた感想
目次
Unityの物理エンジンPhysXというメジャーな物理エンジンを利用している
・ Unity5で PhysX3.3にアップデートされた ・ Unreal Engine4もこれ
現在は NVIDIAが開発しているNVIDIAの開発者登録すればgithubのソースコードも見ることができるhttps://developer.nvidia.com/physx-sdk
ゴルフゲームを構成する物理オブジェクト
・ゴルフコース ・ゴルフボール ・その他の障害物 ・物理マテリアル
物理エンジン周りのアセット (データ )説明
ゴルフコース
Mayaで作成した描画用のメッシュからそのまま当たり判定用のMesh Colliderを作成
ゴルフコース
描画用のメッシュをコリジョンにも使ったのは以下の理由から
・ゲームプレイと密接に関わるので精度を 下げたくなかった
・コリジョンモデルを用意する手間を 減らしたかった
・パフォーマンスが低下するようなら、コリジョン用に 別モデルを用意する予定だったが、その必要はなかった
ゴルフボール
球体のモデルに RigidbodyとSphere Colliderを適用している
直径は 5cmで、実際のボールより少し大きいのは画面に映ったときに見えづらく感じたから(そのため、カップも大きく作ってある )
その他の障害物
地面に配置してある建物や木水面に浮かぶボートなど
その他の障害物パフォーマンス低下を防ぐため描画用のメッシュが細かい場合は粗いコリジョンメッシュを用意している(結局パフォーマンスはそれほど問題にならなかったので こうする必要はなかったのかも )
描画用1506Triangles
コリジョン用218Triangles
物理マテリアル
地形や障害物の Colliderに設定されている物理マテリアルは、物理挙動と地形判定に使用している 例えば、ボールが停止したときに 真下に Raycastして地形を判定
ゴルフボールの挙動について
・ショット時にボールに与える力・ボールの停止制御・コリジョン抜け対策・落下予測地点の計算・グリーン周りの調整・カップ周りの調整
ショット時にボールに与える力
プレイヤーや地形のパラメータから最終的に Rigidbodyに力とトルクを設定 rigidbody.AddForce(force, ForceMode.Impulse); rigidbody.AddTorque(torque, ForceMode.Impulse);
トルクによるボールの回転 (AngularVelocity)は空中でボール軌道が曲がる時のパラメータとしても使っている 複雑な計算はしていなくて AddForceをしているだけ
ボールの停止制御
Rigidbodyが Sleep状態になると停止判定 ・スリープに入った時のイベントは見つからなかったので
Update()で IsSleepingをチェックしている ・ Rigidbodyの SleepVelocityや SleepAngularVelocityも
ボールの転がり調整のために低く設定している
特殊な地形に対するのボールの挙動はRigidbodyの Drag、 AngularDragを調整
・例えば、バンカーに突入したときは 大きな値を設定して Sleep状態に向かうようにする
コリジョン抜け対策
厚みのないメッシュコリジョンと高速に移動するボールとの衝突は判定の通り抜けが多発した ・ 1フレームでボールがメッシュを完全に 突き抜けてしまうと当たり判定が失敗する
・ Rigidbodyの Collision Detectionの設定を
Continuous Dynamicにすると抜けなくなるが
ボールが跳ねる挙動などがおかしくなってしまった
Dont Go Through Things
前フレームから現フレームへの Rigidbodyの移動が メッシュを突き抜けていたら、 メッシュに軽く重なるくらいの位置に戻す処理をしている
・物理マテリアルに設定されている物理挙動も再現できている ・ただし、このゲームでは 1つ問題があった (後述のデバッグ )
現フレームの修正したボールの位置
前フレームのボールの位置
現フレームの突き抜けたボールの位置
http://wiki.unity3d.com/index.php?title=DontGoThroughThings
Dont Go Through Things
地面
落下予測地点の計算
このゲームには落下予測地点と呼ばれる UIがあり、ショットしたボールが地面に落下する地点
・ただし、高低差なしで無風の場合
しかし、物理エンジンを使っているので事前に落下地点を予測できない
・実際にシミュレーションてみないと、 どこに飛ぶかわからない
落下予測地点の計算
実際にいろんな条件でボールをショットしたパターンのデータを事前に作っておいて、ゲームプレイ中はそのデータを補間計算して落下予測地点としている
・クラブの自動選択の時も、このデータを使っている
飛距離のサンプリング
プレイヤーのパワーパラメータのレベル (160段階 ) ×パター以外のすべてのクラブ (13種類 ) ×すべてのカーブショットの弾道 (27種類 ) ×パワーゲージの%(現状は 20%ごとに 5回サンプリング )
= 約 28万回のショットをサンプリング
グリーン周りの調整パターの時にボールが転がるように設定すると外から打ち込んだときにも転がってしまいとてもグリーンに乗りにくい
・物理マテリアルのパラメータだけではどうしても 調整できなかった
グリーンの物理マテリアルを 2つ用意してパターを使う時とそれ以外で切り替えている
・プログラムでも少し調整している
カップ周りの調整
カップ側面でボールが止まる事が稀に発生 (速度が足りなくて Rigidbodyが Sleep状態になる )
結局、その状態を判定してカップ方向に 少しだけ力を加えてカップインさせる というちょっと無理矢理な方法で解決
パフォーマンスについて
・最も重いゴルフコースは?・物理エンジン周りの設定
最も重いゴルフコースは?MeshColliderの数が一番多いのは
スイートシュガーエデン Hole5219個のMeshCollider、合計 95358トライアングル
最も重いゴルフコースは?MeshColliderのトライアングル数が一番多いのは
ミヤビツシマ Hole8164個のMeshCollider、合計 195603トライアングル
物理エンジン周りの設定
動かないオブジェクトにはStaticフラグを付ける
Layer Collision Matrixで衝突判定するレイヤーを必要最小限に設定する
設定はメニューの Edit - Project Settings - Physics
デバッグについてカップインしたとき 1万回に 1回くらいの割合でボールがカップから抜け落ちることがあるということがリリース後に発覚手動では再現しない (開発中は 1度も起きなかった )
自動的にカップにボールを打ち込むプログラムを作って、現象の確認と問題修正
ボール抜け落ちチェック
ボールがカップから落下したら検出される 原因は、前述 Dont Go Through Things の
コリジョン抜け対策のところで、微細な移動の場合はその処理を飛ばしていた為だったらしい
グリーン上のランダムな位置からカップ方向にランダムなパワーで自動的にパッティングを数万回実行
物理エンジン使ってみた感想良かった点
・自前でやるより工数は削減できたと思う ・モバイルでもパフォーマンスは良い
(過度な期待は禁物だけど、他のゲームでも演出などで 気軽に使う事ができると思う )
良くなかった点 (ただし、自前で実装しても同じような問題に遭遇しそう )
・物理マテリアルの調整は面倒 (エンジニア以外に任せることも可能 )
・デバッグも面倒