このページでは

Qt Quick 3D 物理演算 - CharacterController の例

CharacterController の動作を解説します。

テストルームのスクリーンショット

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

シーン

このシーンは、Building.qml で定義された単純な建物で構成されており、詳細については説明しません。(メッシュのbuilding.mesh は Blender を使用して作成されました。balsamツールを使用すれば、building.gltf から再現可能です。)

この建物には3つのトリガーが含まれています:

  • ドアを開くトリガー。Building.qml内で実装されています
  • 何かが内部に入った際にinGravityField プロパティを設定する「gravityField」トリガー。
  • 何かが中に入った際にteleporterTriggered というシグナルを発生させる「teleport」トリガー。

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

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

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
    }
}

キャラクターコントローラーにはシェイプが必要です。CapsuleShape のみがサポートされています。なお、heightプロパティはカプセルの円筒部分の高さを指します。キャラクターの全高は、下部と上部の半球の高さを足し合わせて計算されます:

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 には、PhysicsWorld とは独立した独自のgravity プロパティがあります。一般的な使用例としては、歩行と飛行の切り替えが挙げられます。この例では、キャラクターが「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 プロパティに速度を設定することで定義されます。これにより、キャラクターは進行方向ベクトルを基準に、その速度で移動しようとします。壁に阻まれたり、自由落下状態になったりするため、実際には異なる速度で移動する場合があります。 マウス/キーボード入力は、`wasd ` オブジェクトから取得されます。これは `WasdController` の機能を簡略化したバージョンです。

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

地上を歩く際のWASD操作に関する一般的な慣習に従うため、2つの回転軸は異なる方法で処理されます:

  • 垂直方向の回転は視線の方向を変更しますが、キャラクターが空中に飛び上がったり、地面に潜り込んだりすることはありません。
  • 水平回転は、キャラクターの前進方向を変更します。(これは、物理シミュレーションの実行中は変換を変更してはならないという規則の例外です。キャラクターコントローラーの回転を変更しても、物理エンジンの状態は変化しないため安全です。これは、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
}

ファイル:

画像:

© 2026 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.