Qt Quick 3D Physics - CharacterController の例

CharacterController タイプのデモンストレーションです。

この例では、CharacterController を使用してシーン内のカメラを動かし、一人称視点で見る方法を示します。キャラクタコントローラは、シーンの物理的なジオメトリによって制約され、地面を歩き、階段を上り下りし、トリガーと相互作用するエンティティとして、ユーザーの視点を表現します。

シーン

シーンはBuilding.qmlで定義されたシンプルなビルで構成されています。(メッシュbuilding.mesh はBlenderを使って作られました。balsamツールを使ってbuilding.gltfから再作成できます)。

建物には3つのトリガーがあります:

  • ドアを開けるトリガー。Building.qmlに内部実装されています。
  • gravityField "トリガーは、その中に何かがいるとき、プロパティinGravityField
  • テレポート(teleport)」トリガーは、何かがその中に入ると、シグナルteleporterTriggered

キャラクター・コントローラー

キャラクタ・コントローラの完全なロジックは以下の通りです:

CharacterController {
    id: character
    property vector3d startPos: Qt.vector3d(800, 175, -850)
    position: startPos
    function teleportHome() {
        character.teleport(character.startPos)
        wasd.cameraRotation.x = 180
    }

    collisionShapes: CapsuleShape {
        id: capsuleShape
        diameter: 50
        height: wasd.crouchActive ? 0 : 100
        Behavior on height {
            NumberAnimation { duration: 300 }
        }
    }
    property real characterHeight: capsuleShape.height + capsuleShape.diameter

    sendTriggerReports: true

    movement: Qt.vector3d(wasd.sideSpeed, 0, wasd.forwardSpeed)
    Behavior on movement {
        PropertyAnimation { duration: 200 }
    }

    gravity: building.inGravityField ? Qt.vector3d(0, 100, 0) : physicsWorld.gravity

    eulerRotation.y: wasd.cameraRotation.x
    PerspectiveCamera {
        id: camera
        position: Qt.vector3d(0, character.characterHeight / 2 - 10, 0)
        eulerRotation.x: wasd.cameraRotation.y
        clipFar: 10000
        clipNear: 10
    }
}

キャラクタコントローラにはシェイプが必要です。CapsuleShapeheightプロパティは、カプセルの円柱部分の高さを指すことに注意してください。キャラクタの全高は、底部と上部の半球の高さを足して計算されます:

collisionShapes: CapsuleShape {
    id: capsuleShape
    diameter: 50
    height: wasd.crouchActive ? 0 : 100
    Behavior on height {
        NumberAnimation { duration: 300 }
    }
}
property real characterHeight: capsuleShape.height + capsuleShape.diameter

TriggerBody をトリガするには、キャラクタ コントローラのsendTriggerReports プロパティがtrue に設定されている必要があります:

sendTriggerReports: true

CharacterController gravity PhysicsWorld一般的な使用例は、歩行と飛行を切り替えることです。この例では、キャラクタが「gravityField」トリガーの内側にいるときに、 プロパティを上向きに変更することで、反重力フィールドを実装しています:gravity

gravity: building.inGravityField ? Qt.vector3d(0, 100, 0) : physicsWorld.gravity
位置と移動

teleporterTriggered シグナルが発信されたら、キャラクタの位置と向きを初期位置に戻します。position プロパティは、シミュレーションの実行中には変更しないでください。代わりにteleport 関数を使用してください:

property vector3d startPos: Qt.vector3d(800, 175, -850)
position: startPos
function teleportHome() {
    character.teleport(character.startPos)
    wasd.cameraRotation.x = 180
}

キャラクタの動きは、movement プロパティを速度に設定することで定義します。キャラクタの動きは、 プロパティに速度を設定することで定義されます。キャラクタは、前方ベクトルに対して、その速度で移動しようとします。キャラクタは、壁に遮られたり、自由落下したりするため、最終的に異なる速度で移動することがあります。マウスやキーボードの入力は、WasdController の縮小版であるwasd オブジェクトから行います。

movement: Qt.vector3d(wasd.sideSpeed, 0, wasd.forwardSpeed)
Behavior on movement {
    PropertyAnimation { duration: 200 }
}

2つの回転軸は、地面を歩くときのWASD移動の一般的な慣習に従うために、異なる方法で処理されます:

  • 垂直方向の回転はビューの方向を変えますが、キャラクターを空中に飛ばしたり地面に掘り下げたりはしません
  • 水平方向の回転はキャラクターの前進方向を変える。(これは、物理シミュレーションの実行中にトランスフォームを変更してはいけないというルールの例外です:キャラクタコントローラの回転を変更しても、物理エンジンの状態は変わらないので大丈夫です。movement ベクトルの解釈が変わるだけです)
eulerRotation.y: wasd.cameraRotation.x
PerspectiveCamera {
    id: camera
    position: Qt.vector3d(0, character.characterHeight / 2 - 10, 0)
    eulerRotation.x: wasd.cameraRotation.y
    clipFar: 10000
    clipNear: 10
}

ファイル

画像:

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.