5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PONOSAdvent Calendar 2021

Day 7

DOTSベースのUnity PhysicsはPhysXよりどの程度軽量なのか?

Last updated at Posted at 2021-12-06

PONOS Advent Calendar 2021の7日目の記事です。

昨日は@blockさんでした。

はじめに

Unityの物理演算はPhysXが採用されていますが、既に発表されているように新たにDOTSベースで動作するUnity Physics/Havok Physicsが開発されており、現在Preview版となっています。

Unity Physics/Havok Physicsについてはこちら

こちらによるとUnity Physicsは高速、軽量、ステートレス、カスタマイズ可能と謳われています。
既に色々なところで紹介されていると思いますので、詳しい紹介は割愛し、今回はDOTSベースのUnity Physicsがこれまでのシステムと比較して本当に高速/軽量なのかどうか、試してみたいと思います。

検証内容

動作環境

今回はエディタ実行ではなく、Mac向けのアプリビルドを行ってパフォーマンスを確認します。
私の手元にあるMacBookProを使用します。スペックは以下の通りです。

CPU: Core i5-1038NG7 (Cores: 4, Threads: 8, Clockspeed: 2.0GHz)
Memory: LPDDR4X PC4-29800 32GB
GPU: Iris Plus Graphics G7

使用バージョン

Unity: 2019.4.33f1
 * 2020を使用してもよいのですが、2020.3系でUnity Physicsを使用した場合、Default World DebugStreamというおそらくデバッグ用の何かだと思われる仕組みが、パフォーマンスの大半を使用してしまう現象に遭遇したためです。
PhysX: 4.1
 * 2019.3以降は4.1が使用されている。。はず
Unity Physics: 0.4.1 preview
 ※ 2020.3だと0.6が最新だと思います。

何をするのか

負荷を計測するといっても、実際のゲームでは様々なシーンが想定されますし、一つのケースを見ただけではなんとも言えないとは思いつつも。。今回は単純に多くのCubeを使用してみようと思います。

一定の高さから地面に対して定期的に1000個のCubeを自由落下させます。
Cube一つのサイズは1、Massは0.3で、BoxColliderを持つものとします。
プロジェクトのPhysics関係の設定や、Time関連の設定は同Unityでプロジェクトを新規作成したときのデフォルト値とします。

つまり、定期的に1000個ずつCubeが落下してきて、衝突し、蓄積していきます。この時のFPSの変化を計測してみます。

検証

今回はどちらのバージョンもスクリプトバックエンドにはIL2CPPを選択して行います。

1. 従来版のプロジェクトを作る

ごくごく単純なので手順はほぼ割愛しますが、検証用のプロジェクトでいじったところを簡単に箇条書きします。

  1. 広めの地面を用意する(Colliderもね)
  2. CubeのPrefabを作成し、Rigidbodyを設定し、Massを0.3に設定する
  3. 適当なスクリプトを作成する。ここではこのCubeのPrefabをある程度の高さのところから、縦10x横10x高10に並べて生成するプログラムにしました。
  4. カメラ位置を全体を見渡せるところに移動させる。
  5. 生成タイミングをコントロールしたかったので、Cubeの生成を呼ぶボタンをつけました。
  6. その他、FPSを表示するためのコンポーネントをつけたりなんだりしました。
  7. スクリプトバックエンドをIL2CPPに変更

2. Unity Physics版のプロジェクトを作る

2-1 プロジェクトコピー

先ほど作ったプロジェクトを丸ごとコピー

2-2 パッケージを導入する

PackageManagerでUnity PhysicsHybrid Rendererをインストールします。
Unity PhysicsはGameObjectではなくEntity(ECS)として動作するため、そのままだとレンダリングされません。なので今回はHybrid Rendererを利用しました。

スクリーンショット 2021-12-01 19.29.57.png

(余談ですが、2020系のPackageManagerでは、これらのパッケージが一覧に表示されないようになっていました。設定からPreview Packageを有効にしても、それでも表示されません。
その際のインストール方法はUnityのヘルプデスクにあります。)

2-3 Unity Physicsに切り替える

今回はConvert To Entityコンポーネントを使用します。
このコンポーネントはGameObjectからEntityに自動的に変換するためのコンポーネントです。プログラムから呼び出すAPIも存在しますが、特に必要ないためこれを使用することにしました。

  1. 地面のオブジェクトにConvert To Entityをアタッチする
  2. CubeのPrefabにConvert To Entityをアタッチする

スクリーンショット 2021-12-01 19.29.10.png

以上です。
この状態でゲームを実行すると、地面もCubeもGameObjectからEntityに変換され、ヒエラルキーから消え去ります。
コンバート方法を選べばGameObjectを残したりも出来ます。これらのオブジェクトを操作するためには、DOTS(ECS)を前提に行う必要が出てくるでしょうけれども、今回の検証ではそういったことは一切しないため、単純に変換して終わりです。

3. 従来版 vs Unity Physics版

1000個のときー

多少のスパイクはありますが、この時は双方ともほぼほぼ60FPSを維持できています。
(動きは少し異なっています。このケースではPhysX版のほうが大胆に動いています。)
従来版
スクリーンショット 2021-12-01 19.43.39.png
Unity Physics版
スクリーンショット 2021-12-01 19.44.02.png

3000個のときー

従来版では、新たな1000個が出現し、衝突した時に大きくFPSが落ち、最終的には40FPS前後で落ち着いています。
Unity Physics版では、わずかなスパイクはありますが、一貫してほとんど60FPSから落ちておらず安定しています。
従来版
スクリーンショット 2021-12-01 19.50.45.png
Unity Physics版
スクリーンショット 2021-12-01 19.51.27.png

6000個のときー

従来版では、流石に厳しくなりました。Cubeの出現時や衝突時には10FPSを下回り、平均的には15FPS程度です。
Unity Physics版では、瞬間的なスパイクを除けば、概ね30~35FPS程度で安定しています。しかしFPSは落ちてきましたね。
従来版
スクリーンショット 2021-12-01 19.56.57.png
Unity Physics版
スクリーンショット 2021-12-01 19.57.06.png

10000個のときー

従来版では、2FPSとかになったので割愛します。
Unity Physics版も15FPSまで落ちてきました。
Unity Physics版
スクリーンショット 2021-12-01 20.02.01.png

まとめ

今回の検証では、ほぼほぼ2倍強程度のパフォーマンスの違いが確認できました。
Unity PhysicsはDOTSベースで動作するため、GameObjectを持ちませんし、純粋な物理演算以外の部分でもパフォーマンスに違いが生じていると思います。
また、負荷やFPSの推移をみている限りでは、従来版は出現時や衝突時のスパイクが大きく、一方でDOTSベースのシステムでは全くスパイクが無いわけではないですが、かなり緩やかな変化に感じました。

現在まだPreview版ですが、正式版では更なるパフォーマンスの改善が見込めるのでしょうか!?

ということで、明日も引き続き私の記事です!よろしくお願いします。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?