babylon.js を覚えようステップ9は衝突判定と重力制御です!

いやー、重力とか楽しそうですね。

メッシュだけでなく、カメラにも設定できるようです。

いきましょう!!

説明

f:id:hollywis:20200620210628j:plain

FPSFirst Person Shooter)ゲームをプレイしたことがありますか?

この回では、そのFPS的なカメラの動きをシミュレートします。

カメラは床にあり、地面と衝突しており、シーン内のオブジェクトと衝突している可能性がありますね

では、このFPS的な設定をしていきましょう!

1.重力の設定

シーンにグラビティ(重力)ベクトルをVector3型で設定します。

scene.gravity = new BABYLON.Vector3(0, -9.81, 0);

古典的には、yに重力加速度9.8を下向き(負)に設定すると良いです。

カメラへの適用は、applyGravityプロパティをtrue設定します

camera.applyGravity = true;

2.楕円体を定義する

次の重要なステップは、カメラの周りに楕円体を定義することらしいです。

この楕円体はプレーヤーの幅(プレイヤーサイズ)を表します。

外部のメッシュがこの楕円体に接触すると衝突イベントが発生し、カメラがこのメッシュに近づきすぎないようにすることで、カメラがメッシュにめり込まないようにします。
f:id:hollywis:20200620211011p:plain

babylon.jsカメラの楕円体プロパティのデフォルトはサイズ(0.5、1、0.5)ですが、

値を変更すると、調整された軸に応じて、背が高く、大きく、小さく、薄くなります。

次の例では、カメラの楕円体をデフォルトの楕円体よりも少し大きくします。

//カメラの周りに楕円を定義 (e.g. your player's size)
camera.ellipsoid = new BABYLON.Vector3(1, 1, 1);

カメラの楕円体はオフセット(Offset)され、常に視点が楕円体の上にあります。

camera.ellipsoidOffsetプロパティを更新することにより、この動作を制御できます。

計算は次のようになります。

finalPosition = position – vec3(0, ellipsoid.y, 0) + ellipsoidOffset

衝突を適用する(Apply collision)

最後のステップとして、シーン内の衝突の検知をすることを宣言します。

// Enable Collisions
scene.collisionsEnabled = true;
camera.checkCollisions = true;

そして、どのメッシュがカメラと衝突するか設定出来ます。

これはとても便利ですね!Three.jsではなかった設定です。

ground.checkCollisions = true;
box.checkCollisions = true;

以上です!!

demoはこちら
https://www.babylonjs-playground.com/#4HUQQ

カメラは地面と衝突するまで落ちます。

また、ボックスに近づくとカメラがボックスに衝突します。

メッシュオブジェクトとメッシュオブジェクトの衝突

mesh.ellipsoidプロパティ

mesh.moveWithCollisions(velocity)関数

を使用して、メッシュでも同じことを行うこともできる。

この関数は、指定された速度でメッシュを移動させ、現在のメッシュとcheckCollisionsがアクティブになっているすべてのメッシュとの間に衝突がないかどうかをチェックします。

mesh.ellipsoidOffsetを使用して、メッシュ上で楕円体の中心を移動することもできます(デフォルトでは、楕円体はメッシュの中心にあります)。

var speedCharacter = 8;
var gravity = 0.15;
var character = ここにメッシュを設定;
character.ellipsoid = new BABYLON.Vector3(0.5, 1.0, 0.5); //楕円を定義
character.ellipsoidOffset = new BABYLON.Vector3(0, 1.0, 0); //楕円オフセットを設定(上にずらす)
var forwards = new BABYLON.Vector3(parseFloat(Math.sin(character.rotation.y)) / speedCharacter, gravity, parseFloat(Math.cos(character.rotation.y)) / speedCharacter);
forwards.negate();
character.moveWithCollisions(forwards); //衝突判定ありの前進
// または
var backwards = new BABYLON.Vector3(parseFloat(Math.sin(character.rotation.y)) / speedCharacter, -gravity, parseFloat(Math.cos(character.rotation.y)) / speedCharacter);
character.moveWithCollisions(backwards); // 衝突判定ありの後進

ArcRotateCameraでの衝突

ArcRotateCameraでも衝突をチェックすることができますが、、、

障害物に沿ってスライドする代わりに、衝突が追加されてもこのカメラは移動しません。

衝突を有効にするには、camera.checkCollisions = trueを呼び出します。

次のコードで衝突半径を定義できます。

camera.collisionRadius = new BABYLON.Vector3(0.5, 0.5, 0.5)

まとめ

重力を設定する方法は、シーンに設定して、カメラのapplyGravityをtrueにするだけという。

ものすごく簡単に重力が設定できることを紹介しました。

Three.jsではもう少し複雑ですよね。

また、衝突判定には楕円を対象物の周りに作ってmoveWithCollisionsで移動させることで衝突判定が出来ます。

お次はメッシュの衝突判定をより詳しくいきます!

hollywis.hatenablog.com

Receive the latest news in your email
Table of content
Related articles