本页内容

Qt Quick 3D 物理 - CharacterController 示例

演示了CharacterController 类型。

考场的截图

本示例演示了如何使用CharacterController 在场景中移动摄像机,从而实现第一人称视角。角色控制器将用户的视角表示为一个实体,该实体受场景物理几何体的限制,能够在地面上行走、上下楼梯,并与触发器进行交互。

场景

该场景由一栋简单的建筑组成,该建筑在 Building.qml 中定义,此处不再赘述。(网格角色控制器(building.mesh )使用 Blender 制作,可通过balsam工具从 building.gltf 文件中重建。)

该建筑包含三个触发器:

  • 一个用于打开门的触发器。在 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
    }
}

角色控制器需要一个形状。仅支持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键移动的常见做法,两个旋转轴的处理方式有所不同:

  • 垂直旋转会改变视角方向,但不会使角色飞向空中或钻入地下。
  • 水平旋转会改变角色的前进方向。(这打破了“物理模拟运行时不应更改变换”的规则:更改角色控制器的旋转是安全的,因为这不会改变物理引擎的状态,仅会改变对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.