Playcanvasの使い方#10 エンティティの操作とスペースキーでのジャンプ

この記事では、PlayCanvasを使用して、矢印キーまたはWASDキーでエンティティを操作し、さらにスペースキーでエンティティをジャンプさせる方法を解説します。
初心者の方でも簡単に取り組める内容になっています。

準備

今回は前回作ったプロジェクトを使って説明します。(プロジェクトの作り方はこちら)
前回のプロジェクトの状態をおさらいです。

  • boxエンティティとPlaneエンティティがある状態。
  • boxエンティティには「collision」と「RigidBody (Type:Dynamic)」のコンポーネントがついている。
  • Planeエンティティにもそれぞれ「Collision」と「RigidBody (Type:Static)」のコンポーネントがついている
  • boxエンティティにはスクリプト「taranslateMove.js」がついている

です。
今回はスクリプトを新たに作って、translateMove.jsと付け替えるだけになります。簡単。

新スクリプト「rigidMove.js」を作成

  1. ASSETフォルダ内に新スクリプトrigidMove.jsを作成します。
  2. 作成後、rigidMove.jsをダブルクリックし、編集画面を開きます
  3. 以下のコードをコピペして、保存してください
var RigidMove = pc.createScript('rigidMove');

RigidMove.attributes.add('moveSpeed', { type: 'number', default: 15 });
RigidMove.attributes.add('jumpForce', { type: 'number', default: 7 });
RigidMove.attributes.add('maxSpeed', { type: 'number', default: 20 });
RigidMove.attributes.add('velocityDamping', { type: 'number', default: 5 });

RigidMove.prototype.initialize = function() {
    this.moveDirection = new pc.Vec3();
    this.groundContacts = 0;
    this.entity.collision.on('contact', this.onContact, this);
};

RigidMove.prototype.onContact = function(result) {
    if (result.other.tags.has('Ground')) {
        this.groundContacts++;
    }
};

RigidMove.prototype.update = function(dt) {
    this.moveDirection.set(0, 0, 0);

    if (this.app.keyboard.isPressed(pc.KEY_UP) || this.app.keyboard.isPressed(pc.KEY_W)) {
        this.moveDirection.z += 1;
    }
    if (this.app.keyboard.isPressed(pc.KEY_DOWN) || this.app.keyboard.isPressed(pc.KEY_S)) {
        this.moveDirection.z -= 1;
    }
    if (this.app.keyboard.isPressed(pc.KEY_LEFT) || this.app.keyboard.isPressed(pc.KEY_A)) {
        this.moveDirection.x -= 1;
    }
    if (this.app.keyboard.isPressed(pc.KEY_RIGHT) || this.app.keyboard.isPressed(pc.KEY_D)) {
        this.moveDirection.x += 1;
    }

    if (this.moveDirection.length() && this.groundContacts > 0) {
        var impulse = this.moveDirection.clone().scale(this.moveSpeed * dt);
        this.entity.rigidbody.applyImpulse(impulse);
    }

    var velocity = this.entity.rigidbody.linearVelocity;
    var horizontalVelocity = new pc.Vec3(velocity.x, 0, velocity.z);
    if (horizontalVelocity.length() > this.maxSpeed) {
        horizontalVelocity.normalize().scale(this.maxSpeed);
        this.entity.rigidbody.linearVelocity = new pc.Vec3(horizontalVelocity.x, velocity.y, horizontalVelocity.z);
    }

    if (this.groundContacts > 0) {
        var damping = 1 - (this.velocityDamping * dt);
        this.entity.rigidbody.linearVelocity = new pc.Vec3(velocity.x * damping, velocity.y, velocity.z * damping);
    }

    if (this.app.keyboard.wasPressed(pc.KEY_SPACE) && this.groundContacts > 0) {
        this.entity.rigidbody.applyImpulse(0, this.jumpForce, 0);
    }

    this.groundContacts = 0;
};

このコードは、PlayCanvasでRigidBodyを持つエンティティ(ボックスなど)を矢印キーとWASDキーで移動させ、スペースキーでジャンプさせるためのものです。

  1. RigidMoveスクリプトを作成し、いくつかの属性を追加しています。
    • moveSpeed: 移動速度
    • jumpForce: ジャンプ力
    • maxSpeed: 最大速度
    • velocityDamping: 速度の減衰
  2. initialize関数で初期化を行います。
    • moveDirection: 移動方向を表すベクトル
    • groundContacts: 地面との接触回数
    • onContact: 接触イベントのリスナーを設定
  3. onContact関数では、接触しているエンティティが「Ground」というタグを持っている場合、groundContactsの値を1増やします。
  4. update関数は、フレームごとに呼び出されます。ここでは以下の処理を行います。
    • キー入力に応じて、moveDirectionベクトルを更新
    • 地面との接触がある場合、移動方向に応じたインパルスをリジッドボディに適用
    • 水平方向の速度が最大速度を超えた場合、速度を制限
    • 地面と接触している場合、速度の減衰を適用
    • スペースキーが押され、地面と接触している場合、ジャンプのためのインパルスを適用
    • groundContactsを0にリセット

このコードをエンティティにアタッチすることで、キー入力に応じてエンティティが移動し、スペースキーでジャンプする動作を実現できます。

velocityDamping: 速度の減衰。これを設定しないと、止まる時にピタッと止まらずに、やや滑る感じになってしまうので、いれました。
Playcanvasには摩擦の設定もあるので、それをいじる手もあるのですが、摩擦をいじってもイメージどうりの挙動には中々ならないので。。。。

ちなみに摩擦の設定はエンティティのRigidBodyの中に「Friction」の項目があるので、そこから設定できます。

rigidMove.jsをboxにアタッチ

boxエンティティについている「translateMove」をゴミ箱マークで削除します。

その後スクリプト欄から「rigidMove.js」を選択して、boxにアタッチします。

最後にパースボタン(矢印マーク)を押します

まだ設定はおわりじゃありません。忘れがちな「タグ設定」が最後にあります。

Tagを設定をする

  • Planeエンティティを選択する
  • 右側のインスペクターにあるtagsの空欄をクリック
  • Groundと入力し、【enter】を押す
  • tagsの空欄の下に「Ground ×」と表示されればOK

enterを押さないとタグ設定がされないので、注意してください。空欄の下にタグ名が出てればOKです。
またGround × の×印をクリックでタグを削除できます。スペスミスなどがあった場合は、ここで削除して、再度空欄に入力してください。

Tag設定の理由

rigidMoveの15行目に「if (result.other.tags.has(‘Ground’))」という文言があり、その後もgroundという単語がちらほらあります。
 これは簡単に言うと「Groundという名のタグに◎◎したら〜」的な感じです。
boxエンティティがGroundという名のタグを持つ物体に触れているか、触れていないかをチェックしています。
 最初はGroundという名のタグを持った物体は無かったので、床にタグ設定を行いスクリプトからの指示を受けれるようにしました。

 また、Groundに触れていれば〜という設定は地味に大事で、これがないとboxは空中でもスペースキーを押せば再度ジャンプができてしまいます。
 スペースキー連打で空高く昇っていきます。
それを防ぐために「Groundに触れている時だけジャンプOK、Groundに触れていないとき(浮いているとき)はジャンプNG」という設定を入れています。

LAUNCHで確認

諸々の設定が終わったらLAUNCHで確認します。boxが動いて、かつジャンプするはずです。

こんなものでも愛着がわきます!!

最後に

メタバースやバーチャル空間の制作に専門的なサポートが必要な場合、豊富な事例をもとにした弊社のサービスをご検討ください。プロジェクトの構想から実現まで、総合的にサポートいたします。お気軽に[お問い合わせ]ください。共に新しい価値を創造しましょう。

タイトルとURLをコピーしました