動力および衝撃
インパルスを適用するにはカーソルキーを使用します。トルクを適用してキューブを回転させるには、WASDキーを使用します。Fを長押しすると一定の力を上向きに適用して重力の効果をキャンセルします。
- Rキーを押しすとキューブをリセットします。*
キューブを角で立たせ回転させてみましょう! 使用されている完全なコードはこのページの下部に表示されています。
このチュートリアルでは、力を使用して動的なリジッドボディを制御し、上に示したデモを生成する方法を説明します。力、衝動、トルクの利用とリジッドボディコンポーネントUIを使用して動作をカスタマイズする方法を簡単に説明します。
力のスクリプティング
一定の力を適用
if (app.keyboard.isPressed(pc.KEY_F) ) {
this.entity.rigidbody.applyForce(0, 9.8, 0);
}
Here a force along the global y-axis is applied to the accessed entity when the user presses the F key via applyForce(x, y, z)
. The point of application of the force vector can
also be set.
衝動
if (app.keyboard.isPressed(pc.KEY_LEFT) ) {
this.entity.rigidbody.applyImpulse(-1, 0, 0);
}
キューブにはapplyImpulse(x, y, z)
を通して速度を瞬時に変化を与えるために、x軸の衝撃が与えられています。
トルク
if (app.keyboard.isPressed(pc.KEY_W) ) {
this.entity.rigidbody.applyTorque(-this.torque, 0, 0);
}
トルク (回転力) は applyTorque(x, y, z)
からエンティティに適用されます。
TorqueImpulses
this.entity.rigidbody.applyTorqueImpulse(x, y, z)
角速度への瞬間的な変化はapplyTorqueImpulse(x, y,
z)
を通して適用されます。これは、上記のデモのコードでは使用されていません。
動的なリジッドボディの移動
リジッドボディを移動させるためには、上記の方法でリニア力および回転力(トルク)を適用します。シミュレーションが上書きされ、オブジェクトが衝突する際などに不自然な効果をもたらすことを避けるため、通常はこのようにリジッドボディの位置や速度を直接変更することは避けるべきです。
必要に応じて、新しい'pc.Vec3'値のセットをentity.rigidbody.linearVelocity
またはentity.rigidbody.angularVelocity
に直接割り当てることによって、速度を上書きすることができます。
リジッドボディタイプに関する商大はコリジョン API ページ, pc namespace ページ, fps-コントローラチュートリアル, コリジョンチュートリアルをご確認ください。
一般的な設定
スポットライト、キューブ(モデル、リジッドボディ、衝突、スクリプトコンポーネントを持つエンティティ)、床(モデル、リジッドボディ、衝突コンポーネントを持つ)を含む基本的なシーンを設定しました。キューブのリジッドボディは動的に設定され、床のリジッドボディは静的に設定されています。各ボックスの素材を作成し、目に優しくするために拡散色を変更しました。また、SpotLightとDynamicBodyエンティティの'cast shadows'オプションを有効にしてました。完全な'usingForces'シーンと、このPlayCanvasのアプリのコードはこちら。
制限と制御
アンバランスな力が適用され続けることを防ぐため(つまり、ボディが加速し続け制御不能になることを防ぐため)、いくつかの設定をEditorで行いました。キューブの属性エディタで角度減衰を有効にしました。また、キューブと床の両方で、摩擦を可能にしました。リニア減衰はここでは使用されていませんが、空気抵抗やシミュレートするために使用することができます。また、減速はコードで適用することができます。

ボディのテレポート
新しい位置にボディを即座にテレポートするためにpc.EntityのAPIからsetPosition関数を使用することはできません。物理エンジンが、まだボディが古い場所にあると認識するからです。代わりにリジッドボディコンポーネントのテレポート機能を使用する必要があります。
//code within the update function
this.playerPos = this.entity.getLocalPosition();
// Keeping the cube on screen - cube moves off of one screen edge then appears from the opposite edge.
if (this.playerPos.x < -9.0) {
this.entity.rigidbody.teleport(8.8, this.playerPos.y, this.playerPos.z);
}
if (this.playerPos.x > 9.0) {
this.entity.rigidbody.teleport(-8.8, this.playerPos.y, this.playerPos.z);
}
xの方向に表示領域を越えてキューブが移動した場合、テレポート機能が呼び出され、キューブエンティティが画面上をテレポートされます。if()
宣言をアクティベートし続けないよう、エンティティは比較的極端でない右左の位置にテレポートされます。
キューブのコードをリセット
if (app.keyboard.wasPressed(pc.KEY_R)) {
this.reset();
}
reset: function () {
this.entity.rigidbody.teleport(0, 2, 0);
this.entity.rigidbody.linearVelocity = pc.Vec3.ZERO;
this.entity.rigidbody.angularVelocity = pc.Vec3.ZERO;
}
キューブを元の位置に戻し、上記のようにテレポートされたエンティティの位置にリジッドボディを同期させるリセット機能を用意しました。リセット機能の最後の2行はボディの線速度および角速度をゼロにリセットします。オブジェクトの向きもリセットすることができますが、このコードでは行われません。
完全なコードのリスト
var DynamicBody = pc.createScript('dynamicBody');
// initialize code called once per entity
DynamicBody.prototype.initialize = function() {
this.torque = 7;
this.app.keyboard.on(pc.EVENT_KEYDOWN, this.onKeyDown, this);
this.on('destroy', function() {
this.app.keyboard.off(pc.EVENT_KEYDOWN, this.onKeyDown, this);
}, this);
};
DynamicBody.prototype.onKeyDown = function (event) {
event.event.preventDefault();
};
// update code called every frame
DynamicBody.prototype.update = function(dt) {
//update player's position
this.playerPos = this.entity.getLocalPosition();
var app = this.app;
//keyboard controls and applying forces and moments.
if (app.keyboard.isPressed(pc.KEY_LEFT) ) {
this.entity.rigidbody.applyImpulse(-1, 0, 0);
}
if (app.keyboard.isPressed(pc.KEY_RIGHT) ) {
this.entity.rigidbody.applyImpulse(1, 0, 0);
}
if (app.keyboard.isPressed(pc.KEY_UP) ) {
this.entity.rigidbody.applyImpulse(0, 1, 0);
}
if (app.keyboard.isPressed(pc.KEY_A) ) {
this.entity.rigidbody.applyTorque(0, this.torque, 0);
}
if (app.keyboard.isPressed(pc.KEY_D) ) {
this.entity.rigidbody.applyTorque(0, -this.torque, 0);
}
if (app.keyboard.isPressed(pc.KEY_W) ) {
this.entity.rigidbody.applyTorque(-this.torque, 0, 0);
}
if (app.keyboard.isPressed(pc.KEY_S) ) {
this.entity.rigidbody.applyTorque(this.torque, 0, 0);
}
if (app.keyboard.isPressed(pc.KEY_F) ) {
this.entity.rigidbody.applyForce(0, 9.8, 0);
}
// Keeping the cube on screen - cube moves off of one screen edge then appears from the opposite edge.
if (this.playerPos.x < -9.0) {
this.entity.rigidbody.teleport(8.8, this.playerPos.y, this.playerPos.z);
}
if (this.playerPos.x > 9.0) {
this.entity.rigidbody.teleport(-8.8, this.playerPos.y, this.playerPos.z);
}
// cube reset control
if (app.keyboard.wasPressed(pc.KEY_R) ) {
this.reset();
}
};
DynamicBody.prototype.reset = function () {
this.entity.rigidbody.teleport(0, 2, 0);
this.entity.rigidbody.linearVelocity = pc.Vec3.ZERO;
this.entity.rigidbody.angularVelocity = pc.Vec3.ZERO;
};