Unity を検索

Unity 2018.3 ベータ版における物理関連の変更事項

2018年11月12日 カテゴリ: テクノロジー | 8 分 で読めます
取り上げているトピック
シェア

Is this article helpful for you?

Thank you for your feedback!

Unity 2018.3 における物理関連の主な変更は、3D 物理エンジンの PhysX 3.3.3 から PhysX 3.4.2 へのアップグレードです。その時点での最新版の PhysX が搭載されるのは今回が初めてのことです。私達の目標は、パフォーマンスと安定性を向上させ、プロジェクトのアップグレードをごく簡単に行えるようにすることです。本記事では今回のアップグレードについて、Unity 2018.3 での物理演算の使用に関わる具体的な変更事項や新機能の詳細を含めてご紹介します。

PhysX 3.4 は、計算物理学の分野における数年間の進化の結晶です。従来、PhysX 新バージョンの Unity への組み込みは、そのバージョンが十分に安定したものになるまで 1 年程の期間を置いてから行っていました。今回は、可能な限りのテストを行った上で、最新のバージョンを公開します。

また今回は、既に正常に機能している中核的な部分により重点を置くために、新機能の追加は控え目にしています。目標は退行を出来るだけ無くすことです。ぜひ Unity 2018.3 ベータ版プログラムにご参加の上、お試しになってみてください!

PhysX 3.4 へのアップグレード

PhysX 3.4 は、様々な形で目に見える改善をもたらす大きなリリースです。1 つ目には、非常に多数のバグ修正が行われました。例えば、Convex 対 Convex の衝突検出とフィードバックが大幅に向上したため、PCM 衝突検出が有効になっている場合に発生していた、地面からの意図しない不規則な突起が無くなります。また、細長い三角形に対する物理クエリが改善されたほか、地形との接触計算の精度が向上しました。2 つ目には、物理エンジンによるスレッドへの物理ジョブの追加性能が大幅に向上しました。ブロードフェーズと衝突検出とソルバは記述し直されて出来る限り多くのアトミックなジョブ内に分割されました。この結果、1 フレームのシミュレートに掛かる時間が以前よりも短縮されました。

3 つ目には、物理クエリモジュールが従来の倍速になりました。

PhysX 3.4 には素晴らしい新要素が数多く追加されています。以下に、Unity 2018.3 の対応する機能について、詳しくご紹介して行きます。

マルチシーン物理

従来 Unity では、単一の物理シーンに、すべての Unity シーンからのすべてのボディとコライダーが追加されていました。当然ながら、特定のケースにおいてはこれが制約となってしまうことがあったため、今回、複数の物理シーンの作成を可能にしました。この変更により、特定の Unity シーンにデフォルトの物理シーンを使用させるか専用のローカルのシーンを使用させるかを指定することが可能となりました。追加シーンは、デフォルトのシーンとまったく同様ですが、すべての通常の Physics API に無視される点だけが異なります。これは、すべてのシーンが完全に個別に作成されるためです。追加シーンは様々な使い方ができます。追加シーンは PhysicsScene.Simulate を使って任意の周波数でシミュレートできます(ワールド内の異なる部分が異なる周波数でシミュレートされると考えてください)。またこれとは別の面白い使い方として、軌道を予測するための非表示の物理シーンを作成するために使用することもできます。この改良は、3D 物理と 2D 物理の両方に適用されます。

バッチ物理クエリの追加

バッチ物理クエリは、物理クエリをメインスレッド外で実行する方法のひとつです。通常の API を別のスレッドから実行することはできないため、この API が必要になります。Unity 2018.1 では、メインスレッド外でレイキャストを計算するのに役立つ RaycastCommand.ScheduleBatch を公開しました。Unity 2018.3 ではこれを拡張し、SphereCast、CapsuleCast、BoxCast などの、単一の結果をもたらす他のクエリも追加しました。Unity では現在、将来的なリリースに向けて、Overlap や Sweep などの複数の結果をもたらすクエリの提供を妨げている技術的制約に関して、調査を行っています。

決定論の強化

PhysX では、すべての入力がまったく同じ場合にはシミュレート結果が必ず同じになります。ところが物理エンジンの視点からは多くの要素が「入力」として扱われます。そのひとつは物理シーン自体です。2018.3 より以前は、暗示的な物理シーンの破棄は不可能でした。シーンに含まれるすべてのオブジェクトを破棄することしかできず、それでは不十分でした。これがマルチシーン物理によって簡単に回避可能になります。しかし、もうひとつ頻繁に発生していた問題は、遠くにあって一見他のオブジェクトとインタラクトしていないように見受けられる新しいボディの追加も、シミュレーションの結果を変える可能性があったことです。これは Unity の PhysX がオブジェクトを内部的にグループ分けしていたことに起因していました。この問題は、Physics Settings 内の特殊なオプションを有効にすることで回避可能となりました。パフォーマンス面で多少の負荷は掛かりますが、プロジェクトの実行を大幅に遅延させることはないはずです。

ハイトマップの統一

TerrainCollider が従来使用していた特殊な衝突検出アルゴリズムは、不正確な想定に基づいて接触の計算を行うもので、地形の厚みのような非自明的な要素もいくつか使用していました。Unity 2018.3 における衝突検出は、メッシュとの接触の計算に使用するものと同じアプローチを採用しています。

予測に基づく継続的衝突検出

Unity ではしばらくの間、連続型衝突検知が利用可能なオプションとして提供されていました。しかし、その処理がリニアな性質を持っていることがしばしば問題となっていました。内部的には「速度ベクトルに沿って、現時点から先の軌道にあるボディの走査を一定距離分行い、次の衝突までの時間を計算する」という処理が行われていました。このモデルでは角度の対応は不可能でした。

これが問題となるゲームの例として最も単純な例がピンボールです ― フリッパーは素早く回転する一方でリニアな移動はまったくしません。Unity 2018.3 では、代替的な継続的衝突検出アルゴリズムの追加によってこれが解決されました。このアルゴリズムは、接触点の生成に影響する接触オフセットを増大させることで機能します。その増大された距離に対してオブジェクトの位置が十分に近くなった時に実際に接触マニフォールドを生成します。このモードでは予測的リニア走査は使われなくなっているので、素早く回転または移動する様々なボディとの重なりを検出することから、より正確になる傾向にあります。

従来のアルゴリズム: 新しいアルゴリズム:

ディレクショナル Friction

新しい Friction(摩擦)のタイプ が公開になります ― One Directional Friction Type とTwo Directional Friction Type です。デフォルトの Friction Type は 1 つの接触ペアにつき最大 4 つまでのスカラー制約を作成することで機能します。これは最も速く計算できるモデルで、収束も速く、必要とされるソルバのイテレーション回数が少なくなります。One Directional Friction Type と Two Directional Friction Type は両方とも、接触ペア毎ではなく接触点毎に機能します。これはより正確な結果をもたらし得ますが、収束するのにより多くのソルバのイテレーションを必要とし、接触ペア毎に生成される接触点の数が多い場合は、プロジェクトの実行速度が遅くなる可能性があります。

新しいプロジェクトにおける自動トランスフォームの廃止

デフォルトでは、Unity のトランスフォームへのすべての変更は、必要が見込まれる時点の直前に物理エンジンに同期されていました。つまり、レイキャストやシミュレーションが実行される度に同期されていたということです。同期の処理には少なからず時間がかかるので、その呼び出し回数の削減は理に適っています。このために、すべての自動同期ポイントをオフにする設定が提供されています。ユーザー自身が Physics.SyncTransforms を呼び出す必要があります ― これを行わなかった場合はトランスフォームはシミュレーションの直前にしか同期されません(=FixedUpdate)。

同期ポイントのもうひとつの問題は、同期自体がメインスレッドでしか実行できないことです。つまり、例えば同期を含むレイキャストは含めることができないことになります。基本的に、Unity がよりマルチスレッド指向のエンジンになるに従って、新しいプロジェクトでは自動同期ポイントをオフにしなければならないケースが多くなります。これを踏まえた上で、今回のリリースから、すべての新規プロジェクトの Physics.autoSyncTransforms のデフォルトの値を true から false に変更しています。この改良は、3D 物理と 2D 物理の両方に適用されます。

ガベージを発生させずに接触を取得

接触の情報の取得に伴ってはマネージヒープの割り当てが常に不可避でした。この割り当ては、Collision 構造体のインスタンスを、接触ポイントの配列を含めて、スクリプト内のハンドラー(例えば OnContactStay)に渡すために行われていました。しかし一部のプロジェクトでは、イベントの頻度によってパフォーマンスに悪影響を与えることがありました。

2018.3 では、新しいプロパティ Physics.reuseCollisionCallbacks が公開されました。これはデフォルトでは、既存のプロジェクトをアップグレードした際に挙動を一貫させるためにオフになっています。しかし、オンにすると Collision インスタンスが共有されます。これは事実上、コールバックが発火される度に再使用される Collision クラスのインスタンスが 1 つしかないことを意味します。この結果、ガベージが一切発生しなくなります。ただし、コールバック内で受領される衝突の情報は、必要に応じて手動でコピーされる必要があります。この改良は、3D 物理と 2D 物理の両方に適用されます。

品質向上のために

私達は、本リリースへのアップグレードをごく簡単に行えるようにすることを目標としています。これを実現するため、これまで以上にじっくり時間を掛けてテストとレビューを行う決断をしました。まず、アーリーアダプターの皆様にビルドを提供させていただきました。次に、限定的な機能アップグレードを Unity 2018.2 に実装し、それを 2018.2 アルファ版の期間中にテスト用のスピンオフビルドとして入手可能としました。そしてバージョン 2018.2 の一般公開後にフォーラムでスレッドを立ち上げ、熱心なユーザーの皆様にフィードバックの提供をお願いしました。結果、生産的な意見交換が成され、いくつかのバグ修正と機能追加が行われました。2018.3 ベータ版の公開後、そこにアップグレードブランチをマージし、これが現段階では一週間に 10000 件を超えるエディターのセッションで使用されています。Unity では引き続きフィードバックを募集していますので、ぜひベータ版にご参加のうえ、Physics フォーラムまたは 2018.3 ベータ版フォーラムに投稿をお寄せください!

2018年11月12日 カテゴリ: テクノロジー | 8 分 で読めます

Is this article helpful for you?

Thank you for your feedback!

取り上げているトピック