Qt Quick 3D 物理引擎 - 角色控制器示例
演示了 CharacterController 类型。
本示例展示了如何使用 CharacterController 在场景中移动摄像机,提供第一人称视角。角色控制器代表用户的视点,受到场景物理几何形状的限制,可以在地面上行走,上下楼梯,并与触发器交互。
场景
该场景由一个简单的建筑组成,该建筑在 Building.qml 中定义,将不会详细介绍。(网格 building.mesh
使用 Blender 创建。可以使用 balsam 工具从 building.gltf 中重新创建。)
该建筑包含三个触发器
- 一个打开门的触发器。在 Building.qml 内部实现
- 一个“重力场”触发器,当有东西在它里面时设置属性
inGravityField
- 一个“传送”触发器,当有东西进入它时发出信号
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 有自己的 gravity 属性,独立于 PhysicsWorld。常见的用例是在行走和飞行之间切换。在本示例中,我们通过将 gravity
属性改向上方来实现反重力场,当角色在“gravityField”触发器内部时
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 }
角色的运动是通过将运动属性设置为速度来定义的。角色将尝试以该速度移动,相对于前方向量。由于可能会被墙壁阻挡或处于自由下落状态,角色的实际移动速度可能不同。鼠标/键盘输入来自wasd
对象,它是WasdController的简化版本。
movement: Qt.vector3d(wasd.sideSpeed, 0, wasd.forwardSpeed) Behavior on movement { PropertyAnimation { duration: 200 } }
为了遵循在地面上的WASD移动的常规做法,处理两个旋转轴的方式有所不同。
- 垂直旋转会改变视图方向,但不会使角色飞入空中或钻入地面。
- 水平旋转会改变角色的前方方向。(这是变换不应在物理模拟运行时更改规则的一个例外:改变角色控制器的旋转是安全的,因为它不会改变物理引擎的状态:它只改变了运动向量的解释。)
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
© 2024 The Qt Company Ltd. 本文件中包含的文档贡献是各自所有者的版权。所提供的文档是根据自由软件基金会发布的GNU自由文档许可协议版本1.3的条款许可的。Qt及其相应的标志是The Qt Company Ltd.在芬兰和其他国家/地区的商标。所有其他商标均为其各自所有者的财产。