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
}

文件

图像

© 2024 The Qt Company Ltd. 本文件中包含的文档贡献是各自所有者的版权。所提供的文档是根据自由软件基金会发布的GNU自由文档许可协议版本1.3的条款许可的。Qt及其相应的标志是The Qt Company Ltd.在芬兰和其他国家/地区的商标。所有其他商标均为其各自所有者的财产。