Qt Quick 3D Physics - 字符控制器示例
演示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 。请注意,高度属性指的是胶囊圆柱体部分的高度:字符的总高度是由底部和顶部半球的高度相加计算得出的:
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 蚂蚁拥有自己的 属性,与 无关。常见的用例是在行走和飞行之间切换。在本示例中,当角色处于 "gravityField "触发器内时,我们通过将 属性改为指向上方来实现反重力场:gravity PhysicsWorld 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 }
文件:
- charactercontroller/Building.qml
- charactercontroller/CMakeLists.txt
- charactercontroller/Wasd.qml
- charactercontroller/charactercontroller.pro
- charactercontroller/main.cpp
- charactercontroller/main.qml
- charactercontroller/qml.qrc
图像
- charactercontroller/maps/Tape001_1K_Color.jpg
- charactercontroller/maps/Tape001_1K_NormalGL.jpg
- charactercontroller/maps/Tape001_1K_Roughness.jpg
- charactercontroller/maps/Tiles107_1K_Color.jpg
- charactercontroller/maps/Tiles107_1K_NormalGL.jpg
- charactercontroller/maps/Tiles107_1K_Roughness.jpg
- charactercontroller/maps/Tiles108_1K_Color.jpg
- charactercontroller/maps/sign.png
- charactercontroller/maps/sphere.png
© 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.