Sur cette page

Qt Quick Physique 3D - Exemple de CharacterController

Démonstration du type CharacterController.

Capture d'écran d'une salle de test

Cet exemple montre comment utiliser un CharacterController pour déplacer la caméra dans une scène, en donnant une vue à la première personne. Le contrôleur de personnage représente le point de vue de l'utilisateur en tant qu'entité contrainte par la géométrie physique de la scène, qui marche sur le sol, monte et descend des escaliers et interagit avec des déclencheurs.

La scène

La scène consiste en un simple bâtiment défini dans Building.qml, qui ne sera pas expliqué en détail. (Le maillage building.mesh a été réalisé avec Blender. Il peut être recréé à partir de building.gltf en utilisant l'outil balsam ).

Le bâtiment contient trois triggers :

  • Un déclencheur qui ouvre la porte. Implémenté en interne dans Building.qml
  • Un trigger "gravityField" qui définit une propriété inGravityField lorsque quelque chose se trouve à l'intérieur.
  • Un trigger "teleport" qui émet un signal teleporterTriggered lorsque quelque chose entre dans le bâtiment.

Le contrôleur de personnage

La logique complète du contrôleur de personnage est la suivante :

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

Le contrôleur de personnage a besoin d'une forme. Seule CapsuleShape est prise en charge. La hauteur totale du personnage est calculée en additionnant la hauteur des hémisphères inférieur et supérieur :

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

Pour déclencher un TriggerBody, le contrôleur de caractères doit avoir la propriété sendTriggerReports définie sur true:

sendTriggerReports: true

CharacterController a sa propre propriété gravity, indépendante de PhysicsWorld. Le cas d'utilisation le plus courant est de passer de la marche au vol. Dans cet exemple, nous mettons en œuvre un champ d'antigravité en modifiant la propriété gravity pour qu'elle pointe vers le haut lorsque le personnage se trouve à l'intérieur du déclencheur "gravityField" :

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

Lorsque le signal teleporterTriggered est émis, nous ramenons la position et l'orientation du personnage à sa position initiale. Notez que la propriété position ne doit pas être modifiée lorsque la simulation est en cours d'exécution. Utilisez plutôt la fonction teleport:

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

Le mouvement du personnage est défini en fixant la propriété movement à une vitesse. Le personnage essaiera alors de se déplacer à cette vitesse, par rapport au vecteur avant. Le personnage peut se déplacer à une vitesse différente, car il peut être bloqué par un mur ou être en chute libre. L'entrée souris/clavier provient de l'objet wasd, qui est une version simplifiée de WasdController.

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

Les deux axes de rotation sont gérés différemment, afin de respecter la pratique courante des mouvements WASD lorsque l'on marche sur le sol :

  • La rotation verticale modifie la direction de la vue, mais ne permet pas au personnage de s'élever dans les airs ou de s'enfoncer dans le sol.
  • La rotation horizontale modifie la direction vers l'avant du personnage. (Il s'agit d'une exception à la règle selon laquelle les transformations ne doivent pas être modifiées lorsque la simulation physique est en cours : Il n'y a aucun risque à modifier la rotation du contrôleur du personnage, puisque cela ne change pas l'état du moteur physique : cela change seulement l'interprétation du vecteur 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
}

Fichiers :

Images :

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