【DOTS】Unity Physicsで大量のオブジェクトの物理演算を試す
はじめに
前回の記事でUnity Physicsの公式デモを触ってみました。
今回はUnity Physicsの真価を見るために、大量のオブジェクトを準備して物理演算してみようと思います。
検証環境
- 機種: MacBook Air(m1)
- OS: MacOS Monterey(12.3.1)
- メモリ: 8GB
- Unity: 2021.2.16f1(SILICON)
参考動画
Youtubeに、Unity Physicsを使ってキューブのタワーを召喚して、それを崩すような動画がありました。 動画の検証環境は、i7-8700k、GTX1080tiというかなり高スペックなPCです。
僕のM1 Macでは、どのくらいのオブジェクト数、FPSで処理できるか試してみたいと思います。
プロジェクトの準備
前回使用したUnity Physicsのデモプロジェクトを使いますので、Unityで開いてください。
SceneとPrefabの準備
Sceneを作成する
適当にSceneを作りましょう。
Planeを配置する
HierarchyからPlaneを配置します。 Scaleは(50,1,50)に設定しました。
次のようにコンポーネントを設定します。
- Convert To Entityを追加
- Physics Shapeを追加
- Mesh Colliderを削除
キューブのPrefabを作成する
まず、HierarchyからCubeを配置します。
次のようにコンポーネントを設定します。
- Convert To Entityを追加
- Physics Bodyを追加
- Physics Shapeを追加
- Box Colliderを削除
最後にキューブをPrefabディレクトリにドラッグして、プレハブを生成します。
キューブをジェネレートするスクリプトを書く
TowerGenerator
という名前でスクリプトを作成します。
下のプログラムを入力してください。
using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.Entities; using Unity.Transforms; using UnityEngine.UI; public class TowerGenerator : MonoBehaviour { public GameObject cubePrefab; public int length; public int width; public int height; private Entity _cubeEntity; private EntityManager _entityManager; private BlobAssetStore _blobAssetStore; private GameObjectConversionSettings _settings; void Start() { _entityManager = World.DefaultGameObjectInjectionWorld.EntityManager; _blobAssetStore = new BlobAssetStore(); _settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, _blobAssetStore); _cubeEntity = GameObjectConversionUtility.ConvertGameObjectHierarchy(cubePrefab, _settings); for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { for (int l = 0; l < length; l++) { if (l != 0 && w != 0 && l != length - 1 && w != width - 1) { continue; } Entity cube = _entityManager.Instantiate(_cubeEntity); Translation cubeTranslation = new Translation { Value = new Unity.Mathematics.float3(l, h + 0.5f, w) }; _entityManager.SetComponentData(cube, cubeTranslation); } } } } private void OnDisable() { _blobAssetStore.Dispose(); } // Update is called once per frame void Update() { } }
スクリプトのアタッチ
作成したスクリプトを、シーン上のどのオブジェクトでもいいのでアタッチしてください。 キューブのプレハブをセットするのと、生成するタワーの大きさを設定します。 一旦全て10でやってみます。
実行
動画のように、キューブのタワーが生成されて崩れる様子が見れました。
キューブの数を増やす
タワーの大きさのパラメータを変化させて、実行時のFPSを測ります。 FPSの表示には、Lite FPS Counterというアセットを使用しました。
動画ではフレームレートが揃えられて滑らかに動いていますが、実行時には割とカクカクしています。
パラメータを全て50にした場合
フレームレートは20FPS前後でした。 動画はこちら
パラメータを全て100にした場合
動画のような感じです。フレームレートは8FPS前後でした。 動画はこちら
おわりに
今回は、UnityPhisicsを使って大量のオブジェクトの物理演算をしてみました。
M1 MacでもFPSこと下がりましたが、数万個のオブジェクトの物理演算ができるのはDOTSの恩恵だなと思います。 リアルタイム演算は難しいかもですが、動画のためにレンダリングする等の用途であれば、十分に使えそうです。
みなさまもUnity Physicsを応用されてみてください。