メインコンテンツまでスキップ

はじめに

PlayCanvasの物理演算は、オープンソースのBullet物理エンジンをWebAssemblyに移植したammo.jsによって動作します。読み込みが済んだら、エンティティがどのように動くかを決めるRigidBodyコンポーネントと、形状を与えるCollisionコンポーネントを持つエンティティからシミュレーションを組み立てます。このページでは、ライブラリの読み込み、グローバルな設定、そしてこのセクションの他のすべてのページが前提とするルールを扱います。

物理を有効化

物理演算はオプトインです。ammo.jsは数百キロバイトのサイズがあるため、要求しない限り何も読み込みません。配布は3つのファイルで行われます。WebAssemblyモジュールのammo.wasm.wasm、そのJavaScriptグルーであるammo.wasm.js、そしてWebAssemblyをサポートしないブラウザ向けのasm.jsフォールバックであるammo.jsです。ライブラリが存在するまで、物理コンポーネントは何もしないプレースホルダーです。追加しても何も起こらず、エラーも発生しません。

アプリケーションを作成する前にモジュールを読み込みます。3つのファイルは、エンジンリポジトリのexamples/assets/wasm/ammo/sync-ammo npmパッケージに同梱されています。

pc.WasmModule.setConfig('Ammo', {
glueUrl: 'ammo/ammo.wasm.js',
wasmUrl: 'ammo/ammo.wasm.wasm',
fallbackUrl: 'ammo/ammo.js'
});

// モジュールを待ってから、通常どおりアプリケーションを作成する
await new Promise((resolve) => {
pc.WasmModule.getInstance('Ammo', () => resolve());
});

const app = new pc.Application(canvas);

アプリケーションの開始時にRigidBodyシステムがAmmoグローバルを見つけ、ammo.jsバックエンドをインストールします。pc.Applicationはすべてのコンポーネントシステムを登録します。代わりにpc.AppBasepc.AppOptionsから構築する場合は、pc.CollisionComponentSystempc.RigidBodyComponentSystemジョイントを使うならpc.JointComponentSystemも)をcomponentSystemsに追加してください。Falling Shapesの例に完全な手順があります。

重力 (Gravity)

重力は、すべてのDynamicなRigidBodyに適用される一定の加速度です。デフォルトのワールドY軸方向(真下)に-9.81という値は地球の重力に近いものです。宇宙を舞台にしたゲームではゼロに、月ならもう少し小さな値に設定します。

// 月の重力。古い setGravity() メソッドは非推奨で、このプロパティに置き換えられている。
app.systems.rigidbody.gravity = new pc.Vec3(0, -1.62, 0);

測定の単位

物理エンジンは1ユニットを1メートルとして解釈し、質量はキログラムで測ります。オブジェクトが自然な速さで落下するように、シーンのサイズをそれに合わせてください。身長1.8mのキャラクターは1.8ユニットの高さにします。大きく異なるスケールで作られたシーンもシミュレートはされますが、重力が弱すぎたり強すぎたりして見え、非常に小さな形状は互いをすり抜けやすくなります。

シミュレーションの仕組み

エンジンがシミュレーションを進める方法から、いくつかのルールが導かれます。このセクションの残りはこれらを前提としています。

  • シミュレーションは固定レートでステップします。 毎フレーム、物理ワールドは1/60秒の固定ステップで進み、フレーム時間が必要とする回数(上限あり)だけステップします。そのため、ボディは30fpsでも144fpsでも同じように振る舞います。60Hzより速いディスプレイではステップが1回も実行されないフレームがあり、その場合はボディのトランスフォームが補間されて動きが滑らかに保たれます。
  • Dynamicなボディは物理エンジンが所有します。 各ステップの後、エンジンはすべてのDynamicなボディの位置と回転をエンティティに書き戻します。エンティティのトランスフォームに設定した値は上書きされるため、Dynamicなボディは力、速度、またはteleportで動かします(RigidBodyを参照)。
  • StaticとKinematicなボディは開発者が所有します。 それらのトランスフォームは各ステップの開始時にエンティティから読み取られるため、他のエンティティと同じように動かせます。
  • イベントはステップごとに発火します。 衝突イベントとトリガーイベントは、フレームごとではなく物理ステップごとに1回通知されます。床の上で静止している箱は、静止している間ずっと毎ステップcontactイベントを発生させます。

関連情報