npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

three-player-controller

v0.6.2

Published

Third-person / first-person player controller for three.js (three-mesh-bvh based)

Readme

中文 | English

three-player-controller

NPM Package Github CesiumJS

基于 three.js 的轻量级第一 / 第三人称玩家控制器。提供角色胶囊体碰撞、动画、相机避障、移动平台、动态刚体、车辆控制和 Foot IK,并使用 three-mesh-bvh 加速复杂场景中的碰撞查询。

功能

  • 第一 / 第三人称切换
  • 行走、奔跑、跳跃、飞行
  • 角色胶囊体碰撞与地面检测
  • 相机避障、过肩视角、弹簧相机
  • 静态 / 运动学 / 动态碰撞体
  • 动态球体、盒体及刚体碰撞
  • BVH Worker 异步构建
  • 3D Tiles 流式碰撞体构建
  • 内置车辆物理、悬挂、转向、抓地和手刹
  • Foot IK 插件
  • 自定义动画与 Locomotion Set
  • 移动端虚拟摇杆与按钮
  • 自定义键位与外部输入

示例

在线示例

安装

npm install three-player-controller three-mesh-bvh

本地运行

git clone https://github.com/hh-hang/three-player-controller.git
cd three-player-controller
npm install
npm run dev

浏览器访问 http://localhost:5173/three-player-controller/。

快速开始

import * as THREE from "three";                                                
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";       
import { playerController } from "three-player-controller"; 

const scene = new THREE.Scene();                                           

const camera = new THREE.PerspectiveCamera(
    60,                                                                      
    window.innerWidth / window.innerHeight,                                   
    0.1,                                                                  
    1000,
);

const renderer = new THREE.WebGLRenderer();                                    
renderer.setSize(window.innerWidth, window.innerHeight);                       
document.body.appendChild(renderer.domElement);                                

const controls = new OrbitControls(camera, renderer.domElement);        

// 加载人物模型
const loader = new GLTFLoader();                                              
const playerGltf = await loader.loadAsync("./glb/player.glb");

// 创建玩家控制器
const player = new playerController();     

// 人物控制初始化
await player.init({
    scene,                                  // three.js 场景实例
    camera,                                 // three.js 相机实例
    controls,                               // 外部相机控制器

    // 人物模型、动画与移动参数
    playerModelConfig: {                                                       
        model: playerGltf.scene,            // 外部加载后的模型根节点
        animations: playerGltf.animations,  // 动画片段
        scale: 0.001,                       // 模型缩放
        idleAnim: "idle",                   // 静止动画名
        walkAnim: "walk",                   // 行走动画名
        runAnim: "run",                     // 跑步动画名
        jumpAnim: "jump",                   // 跳跃动画名;或传 ["起跳", "循环", "落地"] 分三段播放
    },

    // 人物初始出生点
    initPos: new THREE.Vector3(0, 0, 0),                                       

    // 初始化时注册的碰撞体
    colliders: [                                                               
        {
            motion: "static",               // 静态碰撞体
            shape: {                        // 碰撞形状配置
                kind: "mesh",               // 使用 Mesh 作为碰撞形状
                source: scene,              // 从该对象收集几何并自动构建 BVH
            },
        },
    ],
});

function animate() {
    requestAnimationFrame(animate);                                            
    player.update();                                                          
    renderer.render(scene, camera);                                          
}

animate();                                                                  

player.update() 内部已经接管传入的相机控制器。渲染循环中不要再次调用 controls.update(),否则可能与内部相机逻辑冲突。

完整参数示例

init()

await player.init({
    // 必填
    scene,    // three.js 场景实例
    camera,   // three.js 相机实例
    controls, // 外部相机控制器,通常为 OrbitControls

    playerModelConfig: {                              // 人物模型、动画与移动参数
        model: playerGltf.scene,                      // 外部加载后的模型根节点
        animations: playerGltf.animations,            // 动画片段
        scale: 0.001,                                  // 模型缩放
        idleAnim: "idle",                              // 静止动画名
        walkAnim: "walk",                              // 行走动画名
        runAnim: "run",                                // 跑步动画名
        jumpAnim: "jump",                              // 跳跃动画名;或传 ["起跳", "循环", "落地"] 分三段播放

        // 方向 / 飞行动画(可选,不填则复用对应默认动画)
        leftWalkAnim: "leftWalk",                      // 左移动画,默认复用 walkAnim
        rightWalkAnim: "rightWalk",                    // 右移动画,默认复用 walkAnim
        backwardAnim: "walkBack",                      // 后退动画,默认复用 walkAnim
        flyAnim: "fly",                                // 飞行动画,默认复用 idleAnim
        flyIdleAnim: "flyIdle",                        // 飞行待机动画,默认复用 idleAnim
        flyHoverForwardAnim: "flyFwd",                 // 飞行前进悬停动画,默认复用 flyAnim
        flyHoverBackAnim: "flyBack",                   // 飞行后退悬停动画,默认复用 flyIdleAnim
        flyHoverLeftAnim: "flyLeft",                   // 飞行左移悬停动画,默认复用 flyIdleAnim
        flyHoverRightAnim: "flyRight",                 // 飞行右移悬停动画,默认复用 flyIdleAnim
        flyHoverUpAnim: "flyUp",                       // 飞行上升悬停动画,默认复用 flyIdleAnim
        flyHoverDownAnim: "flyDown",                   // 飞行下降悬停动画,默认复用 flyIdleAnim
        drivingAnim: "driving",                        // 驾驶循环动画,默认复用 idleAnim

        // 物理参数(可选)
        gravity: -2400,                                // 重力基准值,会按 scale 缩放,默认 -2400
        jumpHeight: 600,                               // 跳跃高度基准值,会按 scale 缩放,默认 600
        speed: 200,                                    // 移动速度基准值,会按 scale 缩放,默认 200
        runSpeed: 600,                                 // 跑步速度基准值,会按 scale 缩放,默认 600
        flySpeed: 2100,                                // 飞行速度基准值,会按 scale 缩放,默认 2100
        acceleration: 30,                              // XZ 加速响应速度,默认 30
        deceleration: 30,                              // XZ 减速响应速度,默认 30

        // 模型参数(可选)
        rotateY: 0,                                    // 人物初始朝向(弧度),默认 0
        headBoneName: "Head",                          // 头部骨骼名,用于第一人称相机挂载
        firstPersonCameraOffset: [0, 40, 30],          // 第一人称相机局部偏移
        capsuleRadiusRatio: 1,                         // 胶囊体半径倍率,默认 1
    },

    // 场景与碰撞(可选)
    initPos: new THREE.Vector3(0, 0, 0),                // 初始出生点,默认 (0, 0, 0)
    colliders: [                                        // 初始化时批量创建的碰撞体;不传则可在 init() 后调用 addCollider()
        {
            motion: "static",                           // 碰撞体运动类型:static / kinematic / dynamic
            shape: {                                    // 碰撞形状配置
                kind: "mesh",                           // Mesh 碰撞形状
                source: world,                          // 碰撞来源,可传 THREE.Object3D 或 THREE.Object3D[]
            },
            useWorker: false,                            // 是否使用 Worker 异步构建 BVH
        },
    ],

    // 相机(可选)
    minCamDistance: 100,                                // 第三人称最小镜头距离,默认 100
    maxCamDistance: 440,                                // 第三人称最大镜头距离,默认 440
    camLookAtHeightRatio: 0.8,                          // 相机看向点高度比例,0=底部,1=顶部,默认 0.8
    thirdMouseMode: 1,                                  // 第三人称鼠标控制模式 0-5,默认 1
    enableZoom: false,                                  // 是否允许滚轮缩放,默认 false
    enableOverShoulderView: false,                      // 是否启用过肩视角,默认 false
    camOverShoulderOffsetRatio: 0.2,                    // 过肩视角横向偏移比例,默认 0.2
    isFirstPerson: false,                               // 初始是否进入第一人称,默认 false
    enableSpringCamera: false,                          // 是否启用弹簧相机,默认 false
    springCameraTime: 0.05,                             // 弹簧相机平滑时间(秒),默认 0.05

    // 其他(可选)
    mouseSensitivity: 5,                                // 鼠标灵敏度,默认 5
    timeScale: 1,                                       // 时间缩放系数,<1 慢动作,>1 快进,默认 1

    keyMap: {                                           // 自定义键位;可传单键、数组多绑或 null 禁用
        forward: ["KeyW", "ArrowUp"],                   // 前进
        backward: ["KeyS", "ArrowDown"],                // 后退
        left: ["KeyA", "ArrowLeft"],                    // 左移
        right: ["KeyD", "ArrowRight"],                  // 右移
        sprint: ["ShiftLeft", "ShiftRight"],            // 冲刺;开车时为手刹
        jump: ["Space"],                                // 跳跃;开车时为刹车
        toggleView: ["KeyV"],                           // 切换第一 / 第三人称
        toggleFly: ["KeyF"],                            // 切换飞行模式
        toggleVehicle: ["KeyE"],                        // 上 / 下车
    },

    isShowMobileControls: true,                         // 移动端是否显示虚拟控制 UI,默认 true
    mobileControls: {                                   // 移动端按钮显隐、图标与布局配置
        joystick: true,                                 // 是否显示虚拟摇杆,默认 true
        jump: {                                         // 跳跃 / 刹车按钮;传 false 可隐藏
            icon: "/icons/custom-jump.svg",             // 跳跃状态自定义图片 URL
            brakeIcon: "/icons/custom-brake.svg",       // 车辆模式下刹车状态自定义图片 URL
            right: 24,                                  // 距离右侧位置(px)
            bottom: 32,                                 // 距离底部位置(px)
            size: 64,                                   // 按钮直径(px),默认 56
        },
        fly: true,                                      // 飞行按钮;true 使用默认样式,false 隐藏
        view: true,                                     // 视角切换按钮;true 使用默认样式,false 隐藏
        vehicle: true,                                  // 上 / 下车按钮;true 使用默认样式,false 隐藏
    },
});

碰撞系统

使用统一的 CollisionWorld 和 addCollider() API。

碰撞体由两个核心属性描述:

{
    motion: "static" | "kinematic" | "dynamic",
    shape: {
        kind: "mesh" | "box" | "sphere",
        // ...
    }
}

静态 Mesh

适用于地形、建筑、墙体和不会移动的场景模型。

const handle = player.addCollider({
    motion: "static",
    shape: {
        kind: "mesh",
        source: world,
    },
    useWorker: true,
});

运动学 Mesh

适用于电梯、移动平台、旋转平台、车辆外观或其它由业务代码控制变换的物体。

const platformCollider = player.addCollider({
    motion: "kinematic",
    shape: {
        kind: "mesh",
        source: platform,
    },
    follow: platform,
    useWorker: true,
});

碰撞体会在每帧跟随 follow.matrixWorld,运行时如果只需要调整已经烘焙的运动学碰撞几何,可以避免重建 BVH。

动态刚体

动态 box 和 sphere 会自动创建内置刚体,由 DynamicBodySystem 进行重力、阻尼、接触、冲量和休眠计算。

动态盒体

const box = new THREE.Mesh(
    new THREE.BoxGeometry(1, 1, 1),
    new THREE.MeshStandardMaterial(),
);
scene.add(box);

player.addCollider({
    motion: "dynamic",
    shape: {
        kind: "box",
        halfExtents: new THREE.Vector3(0.5, 0.5, 0.5),
        position: new THREE.Vector3(0, 5, 0),
    },
    mesh: box,
});

动态球体

const sphere = new THREE.Mesh(
    new THREE.SphereGeometry(0.5),
    new THREE.MeshStandardMaterial(),
);
scene.add(sphere);

player.addCollider({
    motion: "dynamic",
    shape: {
        kind: "sphere",
        radius: 0.5,
        position: new THREE.Vector3(0, 5, 0),
    },
    mesh: sphere,
});

动态刚体支持与静态 Mesh、运动学 Mesh、人物、车辆以及其它动态刚体发生碰撞。

移除与清理

const handle = player.addCollider({
    motion: "static",
    shape: { kind: "mesh", source: object },
});

player.removeCollider(handle);

// 只清除静态碰撞体
player.clearColliders({ motion: "static" });

// 清除全部碰撞体
player.clearColliders();

碰撞分组

import { CollisionGroup } from "three-player-controller";

| 分组 | 说明 | | --- | --- | | CollisionGroup.DEFAULT | 默认场景碰撞。 | | CollisionGroup.CHARACTER | 玩家角色碰撞组。 |
| CollisionGroup.VEHICLE | 车辆碰撞组。 | | CollisionGroup.DEBRIS | 动态杂物、可推动物体等碰撞组。 | | CollisionGroup.ALL | 所有碰撞组的组合,表示允许与全部分组发生碰撞。 |

默认情况下无需设置,会根据 motion 自动使用对应的碰撞组和掩码;也可以通过 groups 和 mask 自定义碰撞过滤:

player.addCollider({
    motion: "dynamic",
    shape: {
        kind: "sphere",
        radius: 0.5,
        position: new THREE.Vector3(),
    },
    groups: CollisionGroup.DEBRIS,
    mask: CollisionGroup.DEFAULT | CollisionGroup.VEHICLE,
});

3D Tiles 流式碰撞

对于 3D Tiles,不建议把整个 Tileset 一次性合并成一个碰撞体。

example/3dtilesScene.js 使用流式策略:

  1. 监听瓦片加载、卸载和可见性变化。
  2. 只跟踪当前已加载瓦片。
  3. 只为人物附近且可见的瓦片创建碰撞体。
  4. 使用 useWorker: true 异步构建 BVH。
  5. 瓦片隐藏、卸载或距离过远时立即 removeCollider()。
  6. 使用进入 / 退出双半径,避免边界附近频繁创建和销毁。

核心形式:

const handle = player.addCollider({
    motion: "kinematic",
    useWorker: true,
    shape: {
        kind: "mesh",
        source: tileScene,
    },
    follow: tileScene,
});

// 瓦片卸载 / 不可见 / 距离过远时移除碰撞体
player.removeCollider(handle);

示例同时演示了地球级大坐标场景中的局部坐标系和 rebase:人物距离局部原点过远时更新局部坐标系,并同步角色、相机和速度,避免大坐标浮点精度问题。

完整实现见 example/3dtilesScene.js。

车辆

const vehicleGltf = await loader.loadAsync("./glb/vehicle.glb"); // 外部加载车辆模型

const vehicle = await player.loadVehicleModel({
    // 必填
    model: vehicleGltf.scene,                             // 外部加载后的车辆模型根节点
    position: new THREE.Vector3(0, 0, 0),                 // 车辆初始世界坐标
    wheelsNames: [                                       // 车轮节点名,顺序:左前、右前、左后、右后
        "Wheel_LF",                                      // 左前轮节点名
        "Wheel_RF",                                      // 右前轮节点名
        "Wheel_LR",                                      // 左后轮节点名
        "Wheel_RR",                                      // 右后轮节点名
    ],
    driverSeatPosition: new THREE.Vector3(-0.6, 0.7, 0.4), // 驾驶位胶囊中心,使用底盘局部坐标

    // 模型 / 驾驶(可选)
    scale: 0.1,                                          // 车辆模型缩放,默认 1
    driverSeatRotation: 0,                               // 驾驶位相对底盘局部的水平旋转(弧度),默认 0
    modelRotation: -Math.PI / 2,                         // 车辆模型绕 Y 轴旋转(弧度),默认 -π/2
    followVehicleDirection: true,                        // 驾驶时镜头是否跟随车辆朝向,默认 true

    // 调试(可选)
    debug: {                                             // 车辆物理调试显示配置
        showPhysicsBox: false,                           // 是否显示底盘物理碰撞盒,默认 false
        showWheelRays: false,                            // 是否显示车轮悬挂射线,默认 false
        showWheelTravel: false,                          // 是否显示车轮 Y 向活动范围,默认 false
        showWheelSpheres: false,                         // 是否显示车轮动态碰撞球,默认 false
    },

    // 底盘(可选)
    chassis: {                                           // 底盘碰撞盒与阻尼参数
        density: 1,                                      // 底盘密度,质量根据碰撞盒体积与密度计算,默认 1
        linearDamping: 0.05,                             // 线阻尼,默认 0.05
        angularDamping: 0.5,                             // 角阻尼,默认 0.5
        clearance: 0.15,                                 // 底盘盒底相对轮胎触地点高度,不传时自动计算
        sizeScale: {                                     // 相对自动 AABB 的底盘碰撞盒尺寸倍率
            x: 1,                                        // X 轴尺寸倍率,默认 1
            y: 1,                                        // Y 轴尺寸倍率,默认 1
            z: 1,                                        // Z 轴尺寸倍率,默认 1
        },
    },

    // 悬挂 / 轮胎(可选)
    suspension: {                                        // 悬挂与轮胎参数
        restLength: 0.3,                                 // 悬挂静止长度,不传时自动计算
        maxTravel: 0.35,                                 // 悬挂最大行程,默认 0.35
        stiffness: 18,                                   // 悬挂刚度,默认 18
        compression: 2.1,                                // 悬挂压缩阻尼,默认 2.1
        relaxation: 2.5,                                 // 悬挂回弹阻尼,默认 2.5
        maxForce: 6000,                                  // 单轮最大悬挂力,默认 6000
        frictionSlip: 8,                                 // 轮胎纵向抓地,默认 8
        sideFrictionStiffness: 1,                        // 轮胎侧向摩擦刚度,默认 1
        rollInfluence: 0.12,                             // 侧向力对车身侧倾的影响,默认 0.12
    },

    // 转向(可选)
    steering: {                                          // 转向参数
        maxSteerAngle: Math.PI / 5,                      // 最大转向角(弧度),默认 π/5
        steerTime: 0.45,                                 // 从中位打到满舵所需时间(秒),默认 0.45
        steerReturnTimeSlow: 0.55,                       // 低速回正时间(秒),默认 0.55
        steerReturnTimeFast: 0.4,                        // 高速回正时间(秒),默认 0.4
        highSpeedSteerScale: 0.3,                        // 最高车速时最大转向比例,默认 0.3
    },

    // 抓地 / 手刹(可选)
    grip: {                                              // 过弯抓地与手刹参数
        maxG: 1.2,                                       // 最大侧向加速度(g),默认 1.2
        sideFrictionIdle: 1,                             // 直线行驶时侧向摩擦,默认 1
        sideFrictionFrontMin: 0.55,                      // 高负载下前轮侧向摩擦下限,默认 0.55
        sideFrictionRearMin: 0.45,                       // 高负载下后轮侧向摩擦下限,默认 0.45
        handbrakeRearFriction: 0.35,                     // 手刹时后轮侧向摩擦,默认 0.35
        handbrakeRearDriveScale: 0.65,                   // 手刹时后轮驱动力比例,默认 0.65
        handbrakeReleaseTime: 0.15,                      // 松开手刹后的恢复时间(秒),默认 0.15
        wheelbaseRatio: 0.55,                            // 轴距相对车长比例,默认 0.55
    },

    // 动力(可选)
    power: {                                             // 车辆动力参数
        maxSpeed: 100,                                   // 最高速度基准值(km/h),会按 scale 缩放,默认 100
        acceleration: 5,                                 // 加速度基准值(m/s²),会按 scale 缩放,默认 5
        deceleration: 5,                                 // 制动减速度基准值(m/s²),会按 scale 缩放,默认 5
    },
});

运行时:

player.resetVehicle();                                  // 翻正当前驾驶车辆,并清零线速度和角速度
player.setVehicleScale(vehicle, 0.12);                  // 动态修改车辆整体缩放
player.setVehicleClearance(vehicle, 0.15);              // 调整底盘碰撞盒离地间隙
player.setVehicleChassisSizeScale(vehicle, {            // 调整底盘碰撞盒相对自动 AABB 的尺寸倍率
    x: 1,                                               // X 轴尺寸倍率
    y: 0.9,                                             // Y 轴尺寸倍率
    z: 1,                                               // Z 轴尺寸倍率
});
player.setVehiclePhysicsDebug(true);                    // 显示 / 隐藏车辆底盘物理碰撞盒

Foot IK 插件

import { FootIK } from "three-player-controller/foot-ik";

const footIK = new FootIK({
    // 手动指定人物骨骼映射;不传时会尝试自动匹配常见骨骼名
    skeleton: {                                         
        hips: "mixamorigHips",                          // 髋部 / 骨盆骨骼名

        // 左右腿骨骼配置
        legs: {                                         
            left: {                                     
                upper: "mixamorigLeftUpLeg",            // 左大腿骨骼
                lower: "mixamorigLeftLeg",              // 左小腿骨骼
                foot: "mixamorigLeftFoot",              // 左脚骨骼
                toe: "mixamorigLeftToeBase",            // 左脚趾骨骼
            },
            right: {                                   
                upper: "mixamorigRightUpLeg",           // 右大腿骨骼
                lower: "mixamorigRightLeg",             // 右小腿骨骼
                foot: "mixamorigRightFoot",             // 右脚骨骼
                toe: "mixamorigRightToeBase",           // 右脚趾骨骼
            },
        },
    },

    soleSkinThickness: 3,                               // 脚骨到鞋底的蒙皮厚度补偿
});

player.use(footIK);                                     // 将 Foot IK 插件注册到玩家控制器

运行时:

footIK.setEnabled(false);                 // 启用 / 禁用 Foot IK
footIK.setDebugEnabled(true);             // 显示 / 隐藏 Foot IK 调试辅助
player.unuse(footIK);                     // 从玩家控制器中卸载 Foot IK 插件
footIK.dispose();                         // 释放 Foot IK 创建的调试对象和相关资源

player.destroy() 会自动销毁已注册插件。

完整示例见 example/footIK.js。

API

生命周期与核心

| 方法 | 说明 | | --- | --- | | init(opts, callback?) | 初始化控制器。 | | update(dt?) | 每帧更新人物、碰撞、动态刚体、车辆、相机和动画。 | | destroy() | 销毁控制器并释放资源。 | | reset(pos?) | 将角色重置到指定位置或初始位置。 | | switchPlayerModel(options) | 使用 PlayerModelOptions 运行时切换角色模型。 | | use(plugin) | 注册插件。 | | unuse(plugin) | 卸载插件。 | | getPlugins() | 获取当前插件列表副本。 |

碰撞

| 方法 | 说明 | | --- | --- | | addCollider(desc) | 添加静态 / 运动学 / 动态碰撞体,返回 ColliderHandle。 | | removeCollider(handle) | 按句柄或 id 移除碰撞体。 | | clearColliders(filter?) | 清除碰撞体,可按 motion 过滤。 | | getColliderMeshes(options?) | 获取当前人物查询使用的 Mesh 碰撞体。 | | isStaticColliderUsable() | 是否存在已经完成 BVH 构建的静态 Mesh。 | | getActiveKinematicCollider() | 获取当前角色站立的运动学碰撞体。 | | getActiveDynamicBody() | 获取当前角色站立的动态刚体。 | | getDynamicBodies() | 获取全部动态刚体。 | | removeDynamicBody(body) | 移除动态刚体。 | | clearDynamicBodies() | 清除全部动态刚体。 | | raycastDynamicGround(...) | 向下查询动态刚体表面。 |

状态

| 方法 | 返回内容 | | --- | --- | | getPosition() | 当前角色位置。 | | getVelocity() | 当前角色速度。 | | getIsFirstPerson() | 是否第一人称。 | | getIsFlying() | 是否飞行。 | | getIsOnGround() | 是否在地面。 | | getGroundSupport() | 当前最终地面支撑点和世界空间法线。 | | getCurrentDelta() | 当前帧实际使用的时间步长。 | | getControllerMode() | 0 人物,1 车辆。 | | getPlayerModel() | 当前人物模型。 | | getPlayerCapsule() | 玩家胶囊体。 | | getActiveVehicle() | 当前驾驶车辆。 | | getAllVehicles() | 所有已加载车辆。 | | getCurrentPlayerAnimationName() | 当前动画片段名。 | | getCurrentLocomotionSet() | 当前 Locomotion Set。 | | getCenterScreenRaycastHit() | 屏幕中心射线结果。 |

运行时控制

| 方法 | 说明 | | --- | --- | | setInput(input) | 注入外部输入。 | | setKeyMap(map?) | 自定义或恢复默认键位。 | | setMouseSensitivity(v) | 设置鼠标灵敏度。 | | setPlayerScale(v) | 动态修改人物缩放。 | | setPlayerSpeed(v) | 设置行走速度。 | | setPlayerRunSpeed(v) | 设置跑步速度。 | | setPlayerFlySpeed(v) | 设置飞行速度。 | | setJumpHeight(v) | 设置跳跃高度。 | | setGravity(v) | 设置重力。 | | setMinCamDistance(v) | 设置第三人称最小镜头距离。 | | setMaxCamDistance(v) | 设置第三人称最大镜头距离。 | | setCamLookAtHeightRatio(v) | 设置相机看向点高度比例。 | | setCamOverShoulderOffsetRatio(v) | 设置过肩横向偏移比例。 | | setThirdMouseMode(v) | 设置第三人称鼠标模式。 | | setEnableZoom(v) | 开关滚轮缩放。 | | setOverShoulderView(v) | 开关过肩视角。 | | setEnableToward(v) | 开关鼠标驱动朝向。 | | setSkipCapsuleCollision(v) | 临时跳过人物胶囊碰撞。 | | changeView() | 切换第一 / 第三人称。 | | setFirstPersonCamera(v?) | 直接进入第一人称。 |

调试

player.setColliderDebug(true);                       // 显示 / 隐藏静态与运动学 Mesh 碰撞线框
player.setPlayerCapsuleDebug(true);                  // 显示 / 隐藏玩家胶囊体线框
player.setDynamicBodyDebug(true);                    // 显示 / 隐藏动态刚体碰撞线框
player.setVehiclePhysicsDebug(true);                 // 显示 / 隐藏车辆底盘物理碰撞盒

动画

| 方法 | 说明 | | --- | --- | | playPlayerAnimationByName(name, fade?) | 按动画片段名直接播放角色动画。 | | registerAnimation(key, clipName, opts?) | 注册自定义动画片段。 | | playAnimation(key, opts?) | 播放已注册的自定义动画。 | | registerLocomotionSet(setName, map) | 注册一套移动动画集合,用于替换内置移动动画。 | | switchLocomotionSet(setName, fade?) | 切换到指定的移动动画集合。 |

registerAnimation

player.registerAnimation(key, clipName, {
    loop?: boolean,              // 是否循环播放,默认 true
    timeScale?: number,          // 动画播放放缩,默认 1
    duration?: number,           // 动画播放时长,默认 0
    clampWhenFinished?: boolean, // 是否在播放结束后将动画时间重置为 0,默认 false
    onFinished?: () => void,     // 动画播放结束后触发
});

duration 与 timeScale 同时设置时,duration 优先生效。

playAnimation

player.playAnimation(key, {
    fade?: number,          // 过渡时长(秒),默认 0.18
    force?: boolean,        // 为 true 时强制从头重播,即使当前已在播放该动画
    returnToPrev?: boolean, // 仅对 LoopOnce 动画生效,播放结束后自动恢复上一个动画状态
});

registerLocomotionSet

支持的 key:idle | walking | walking_backward | running | jumping | flyidle | flying,填写的 key 会替换对应内置动画,未填的保持原有动画。

player.registerLocomotionSet("combat", {
    idle: "CombatIdle",
    walking: "CombatWalk",
    walking_backward: "CombatBack",
    running: "CombatRun",
    jumping: "CombatJump",
    flyidle: "CombatFlyIdle",
    flying: "CombatFly",
});

默认键位

| 动作 | 默认键 | 功能 | | --- | --- | --- | | 前进 | W / ArrowUp | 前进 | | 后退 | S / ArrowDown | 后退 | | 左移 | A / ArrowLeft | 左移 | | 右移 | D / ArrowRight | 右移 | | 冲刺 | Shift | 人物冲刺;车辆手刹 | | 跳跃 | Space | 跳跃;飞行上升;车辆刹车 | | 切换视角 | V | 第一 / 第三人称 | | 飞行 | F | 开关飞行 | | 上 / 下车 | E | 车辆交互 | | 视角 | 鼠标 | 控制视角 |

自定义键位

通过 keyMap 可以把上表的任意动作改绑到其它按键,或禁用某个动作。键名使用 KeyboardEvent.code(如 "KeyE"、"ArrowUp"、"Space",注意是 "KeyE" 而非 "e")。

每个动作三种取值:

  • 不填 → 使用默认键
  • 字符串 / 字符串数组 → 替换为指定按键(数组可绑定多个键)
  • null → 禁用该动作(任何键都不会触发)

初始化时配置:

await player.init({
    // ...
    keyMap: {
        forward: "KeyE",          // 改为按 E 前进(替换默认 W / ↑)
        jump: null,               // 禁用跳跃
        left: ["KeyA", "KeyJ"],   // 同时绑定 A 和 J
        // 其余动作未填,保持默认键
    },
});

运行时切换键位方案:

player.setKeyMap({ forward: "KeyI", backward: "KeyK" }); // 应用新键位
player.setKeyMap();                                      // 恢复全部默认

外部输入

player.setInput({
    moveX: number,        // 水平移动轴,范围 -1~1,正数向右
    moveY: number,        // 纵向移动轴,范围 -1~1,正数向前
    lookDeltaX: number,   // 视角水平增量,通常来自 mousemove 的 movementX
    lookDeltaY: number,   // 视角垂直增量,通常来自 mousemove 的 movementY
    jump: boolean,        // 跳跃,持续状态(true=按下,false=松开);飞行时控制上升;开车时为刹车
    shift: boolean,       // 人物冲刺,开车时为手刹,持续状态(true=按下,false=松开)
    toggleView: boolean,  // 触发式,传 true 切换第一/第三人称视角
    toggleFly: boolean,   // 触发式,传 true 切换飞行模式
    toggleVehicle: boolean, // 触发式,传 true 上车 / 下车
});

事件

player.onAnimationChange = (name, action) => {};   // 角色当前动画切换时触发
player.onBeforeViewChange = (isFirstPerson) => {}; // 第一 / 第三人称切换前触发
player.onViewChange = (isFirstPerson) => {};       // 第一 / 第三人称切换后触发
player.onGroundChange = (onGround) => {};          // 落地状态变化时触发
player.onVehicleEnter = (vehicle) => {};           // 上车完成后触发
player.onVehicleExit = (vehicle) => {};            // 下车完成后触发
player.onTowardChange = (dx, dy, speed) => {};     // 朝向 / 视角输入更新时触发

主要配置

PlayerControllerOptions

| 字段 | 类型 | 必填 | 默认值 | 说明 | | --- | --- | --- | --- | --- | | scene | THREE.Scene | 是 | — | three.js 场景实例。 | | camera | THREE.PerspectiveCamera | 是 | — | three.js 相机实例。 | | controls | any | 是 | — | 外部相机控制器,通常为 OrbitControls。 | | playerModelConfig | PlayerModelOptions | 是 | — | 角色模型与参数配置。 | | initPos | THREE.Vector3 | 否 | (0, 0, 0) | 初始出生点。 | | colliders | ColliderDesc[] | 否 | — | 初始化时批量注册碰撞体。 | | mouseSensitivity | number | 否 | 5 | 鼠标灵敏度。 | | minCamDistance | number | 否 | 100 | 第三人称最小镜头距离。 | | maxCamDistance | number | 否 | 440 | 第三人称最大镜头距离。 | | isShowMobileControls | boolean | 否 | true | 是否在移动端显示虚拟控制 UI。 | | mobileControls | MobileControlsOptions | 否 | 全部显示 | 移动端按钮显隐、图标与布局配置。 | | thirdMouseMode | 0 \| 1 \| 2 \| 3 \| 4 \| 5 | 否 | 1 | 第三人称视角下的鼠标控制模式(0:隐藏鼠标,控制朝向及视角;1:隐藏鼠标,仅控制视角;2:显示鼠标,拖拽控制朝向及视角;3:显示鼠标,拖拽仅控制视角;4:显示鼠标,拖拽控制视角且人物朝向跟随相机水平方向;5:隐藏鼠标,控制视角且人物朝向跟随相机水平方向) | | enableZoom | boolean | 否 | false | 是否允许滚轮缩放。 | | enableOverShoulderView | boolean | 否 | false | 是否启用过肩视角。 | | camOverShoulderOffsetRatio | number | 否 | 0.2 | 第三人称相机过肩视角横向偏移比例。 | | isFirstPerson | boolean | 否 | false | 初始化时是否直接进入第一人称。 | | enableSpringCamera | boolean | 否 | false | 是否启用弹簧相机(目标点以弹簧阻尼跟随角色)。 | | springCameraTime | number | 否 | 0.05 | 弹簧平滑时间(秒),越小跟随越紧。 | | camLookAtHeightRatio | number | 否 | 0.8 | 第三人称相机看向点高度比例(0=胶囊底部,1=顶部)。 | | timeScale | number | 否 | 1 | 时间缩放系数,<1 慢动作,>1 快进。 | | keyMap | KeyMap | 否 | 默认键位 | 自定义键位映射,详见自定义键位。 |

PlayerModelOptions

| 字段 | 类型 | 必填 | 默认值 | 说明 | | --- | --- | --- | --- | --- | | model | THREE.Object3D | 二选一 | — | 已加载的人物模型根节点。与 url 互斥。 | | animations | THREE.AnimationClip[] | 与 model 同用 | — | 人物动画片段。与 model 一起传入。 | | url | string | 二选一 | — | 人物模型路径(GLB/GLTF)。 | | scale | number | 是 | — | 人物模型缩放。 | | idleAnim | string | 是 | — | Idle 动画名。 | | walkAnim | string | 是 | — | Walk 动画名。 | | runAnim | string | 是 | — | Run 动画名。 | | jumpAnim | string \| [string, string, string] | 是 | — | 跳跃动画名。传字符串播放单一动画;传三元素数组 [起跳, 循环, 落地] 分三阶段播放,落地后自动衔接移动动画。 | | leftWalkAnim | string | 否 | walkAnim | 左移动画名,不填则复用 walkAnim。 | | rightWalkAnim | string | 否 | walkAnim | 右移动画名,不填则复用 walkAnim。 | | backwardAnim | string | 否 | walkAnim | 后退动画名,不填则复用 walkAnim。 | | flyAnim | string | 否 | idleAnim | 飞行动画名,不填则复用 idleAnim。 | | flyIdleAnim | string | 否 | idleAnim | 飞行待机动画名,不填则复用 idleAnim。 | | flyHoverForwardAnim | string | 否 | flyAnim | 飞行前进时的悬停动画名,不填则复用 flyAnim。 | | flyHoverBackAnim | string | 否 | flyIdleAnim | 飞行后退时的悬停动画名,不填则复用 flyIdleAnim。 | | flyHoverLeftAnim | string | 否 | flyIdleAnim | 飞行左移时的悬停动画名,不填则复用 flyIdleAnim。 | | flyHoverRightAnim | string | 否 | flyIdleAnim | 飞行右移时的悬停动画名,不填则复用 flyIdleAnim。 | | flyHoverUpAnim | string | 否 | flyIdleAnim | 飞行上升时的悬停动画名,不填则复用 flyIdleAnim。 | | flyHoverDownAnim | string | 否 | flyIdleAnim | 飞行下降时的悬停动画名,不填则复用 flyIdleAnim。 | | drivingAnim | string | 否 | idleAnim | 驾驶循环动画名,不填则复用 idleAnim。 | | gravity | number | 否 | -2400 | 重力基准值(按 scale 缩放)。 | | jumpHeight | number | 否 | 600 | 跳跃高度基准值(按 scale 缩放)。 | | speed | number | 否 | 200 | 移动速度基准值(按 scale 缩放)。 | | runSpeed | number | 否 | 600 | 跑步速度基准值(按 scale 缩放)。 | | flySpeed | number | 否 | 2100 | 飞行速度基准值(按 scale 缩放)。 | | rotateY | number | 否 | 0 | 人物初始朝向(弧度),用于改变模型初始化面朝方向。 | | headBoneName | string | 否 | — | 头部骨骼或节点名称,用于第一人称相机挂载。 | | firstPersonCameraOffset | [number, number, number] | 否 | 有内置默认值 | 第一人称相机局部偏移;有 headBoneName 则相对头骨骼,否则相对胶囊体。 | | capsuleRadiusRatio | number | 否 | 1 | 胶囊体半径倍率,用于微调碰撞宽度。 | | acceleration | number | 否 | 30 | XZ 方向加速响应速度,值越大加速越快。 | | deceleration | number | 否 | 30 | XZ 方向减速响应速度,值越大停止越快。 |

MobileControlsOptions

| 字段 | 类型 | 必填 | 默认值 | 说明 | | --- | --- | --- | --- | --- | | joystick | boolean | 否 | true | 是否显示支持 360° 连续方向的摇杆。 | | jump | boolean \| JumpButtonOptions | 否 | true | 跳跃/刹车按钮;false 隐藏,对象可自定义图片和布局。 | | fly | boolean \| MobileButtonOptions | 否 | true | 飞行按钮;false 隐藏,对象可自定义图片和布局。 | | view | boolean \| MobileButtonOptions | 否 | true | 视角切换按钮;false 隐藏,对象可自定义图片和布局。 | | vehicle | boolean \| MobileButtonOptions | 否 | true | 上下车按钮;false 隐藏,对象可自定义图片和布局。 |

MobileButtonOptions / JumpButtonOptions

| 字段 | 类型 | 必填 | 默认值 | 说明 | | --- | --- | --- | --- | --- | | left / right | number | 否 | 内置位置 | 按钮距离左侧或右侧的位置(px)。设置 left 且未设置 right 时会清除默认右侧定位。 | | top / bottom | number | 否 | 内置位置 | 按钮距离顶部或底部的位置(px)。设置 top 且未设置 bottom 时会清除默认底部定位。 | | size | number | 否 | 56 | 圆形按钮直径(px)。 | | icon | string | 否 | 英文标签 | 自定义图片 URL。 | | brakeIcon | string | 否 | BRAKE 标签 | 仅用于 JumpButtonOptions,设置车辆模式下的刹车图片 URL。 |

ColliderDesc

| 字段 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | motion | "static" \| "kinematic" \| "dynamic" | — | 碰撞体运动类型。 | | shape | ColliderShape | — | 碰撞形状配置,支持 mesh、box、sphere。 | | groups | number | 根据 motion 自动设置 | 当前碰撞体所属碰撞组。 | | mask | number | 根据 motion 自动设置 | 当前碰撞体允许发生碰撞的分组掩码。 | | useWorker | boolean | false | mesh + source 时是否使用 Worker 异步构建 BVH。 | | userData | unknown | — | 自定义业务数据。 | | follow | THREE.Object3D | — | kinematic 碰撞体跟随的场景对象。 | | density | number | 1 | dynamic 刚体密度,用于计算质量。 | | restitution | number | 0.2 | dynamic 刚体弹性系数。 | | friction | number | 0.6 | dynamic 刚体摩擦系数。 | | linearDamping | number | 0.4 | dynamic 刚体线阻尼。 | | angularDamping | number | 0.6 | dynamic 刚体角阻尼。 | | gravity | number | 内部默认值 | dynamic 刚体重力。 | | velocity | THREE.Vector3 | (0,0,0) | dynamic 刚体初始线速度。 | | angularVelocity | THREE.Vector3 | (0,0,0) | dynamic 刚体初始角速度。 | | mesh | THREE.Mesh | — | dynamic box / sphere 创建内置刚体时必须提供的可视化 Mesh。 | | simulate | boolean | true | 是否由内置动态刚体系统进行模拟。 |

ColliderShape

Mesh

| 字段 | 类型 | 说明 | | --- | --- | --- | | kind | "mesh" | Mesh 碰撞形状。 | | source | THREE.Object3D \| THREE.Object3D[] | 从对象中收集几何、合并碰撞网格并构建 BVH。 | | mesh | THREE.Mesh | 直接注册已经准备好的碰撞 Mesh。 |

Box

| 字段 | 类型 | 说明 | | --- | --- | --- | | kind | "box" | 盒体碰撞形状。 | | halfExtents | THREE.Vector3 | 盒体半尺寸,即完整尺寸的一半。 | | position | THREE.Vector3 | 初始世界坐标,可选。 | | quaternion | THREE.Quaternion | 初始世界旋转,可选。 |

Sphere

| 字段 | 类型 | 说明 | | --- | --- | --- | | kind | "sphere" | 球体碰撞形状。 | | radius | number | 球体半径。 | | position | THREE.Vector3 | 初始世界坐标,可选。 |

VehicleOptions

基础参数

| 字段 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | model | THREE.Object3D | — | 外部加载后的车辆模型根节点。 | | position | THREE.Vector3 | — | 车辆初始世界坐标。 | | wheelsNames | [string, string, string, string] | — | 车轮节点名数组,顺序为左前、右前、左后、右后。 | | driverSeatPosition | THREE.Vector3 | — | 驾驶位胶囊中心,车辆底盘局部坐标。 | | scale | number | 1 | 车辆模型缩放。 | | driverSeatRotation | number | 0 | 驾驶位相对车辆底盘局部的水平旋转(弧度)。 | | modelRotation | number | -Math.PI / 2 | 车辆模型绕 Y 轴的初始旋转。 | | followVehicleDirection | boolean | true | 驾驶时镜头是否跟随车辆朝向。 | | debug | VehicleDebugOptions | — | 车辆物理调试显示配置。 | | chassis | VehicleChassisOptions | — | 底盘碰撞盒与阻尼配置。 | | suspension | VehicleSuspensionOptions | — | 悬挂与轮胎配置。 | | steering | VehicleSteeringOptions | — | 转向配置。 | | grip | VehicleGripOptions | — | 抓地和手刹配置。 | | power | VehiclePowerOptions | — | 动力配置。 |

debug

| 字段 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | showPhysicsBox | boolean | false | 显示底盘物理碰撞盒。 | | showWheelRays | boolean | false | 显示车轮悬挂射线。 | | showWheelTravel | boolean | false | 显示车轮 Y 向活动范围。 | | showWheelSpheres | boolean | false | 显示车轮动态碰撞球。 |

chassis

| 字段 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | density | number | 1 | 底盘密度,质量根据碰撞盒体积与密度计算。 | | linearDamping | number | 0.05 | 底盘线阻尼。 | | angularDamping | number | 0.5 | 底盘角阻尼。 | | clearance | number | 自动计算 | 底盘盒底相对轮胎触地点高度。 | | sizeScale.x | number | 1 | 底盘碰撞盒 X 轴尺寸倍率。 | | sizeScale.y | number | 1 | 底盘碰撞盒 Y 轴尺寸倍率。 | | sizeScale.z | number | 1 | 底盘碰撞盒 Z 轴尺寸倍率。 |

suspension

| 字段 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | restLength | number | 自动计算 | 悬挂静止长度。 | | maxTravel | number | 0.35 | 悬挂最大行程。 | | stiffness | number | 18 | 悬挂刚度。 | | compression | number | 2.1 | 悬挂压缩阻尼。 | | relaxation | number | 2.5 | 悬挂回弹阻尼。 | | maxForce | number | 6000 | 单轮最大悬挂力。 | | frictionSlip | number | 8 | 轮胎纵向抓地。 | | sideFrictionStiffness | number | 1 | 轮胎侧向摩擦刚度。 | | rollInfluence | number | 0.12 | 侧向力对车身侧倾的影响。 |

steering

| 字段 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | maxSteerAngle | number | Math.PI / 5 | 最大转向角,单位为弧度。 | | steerTime | number | 0.45 | 从中位打到满舵所需时间,单位为秒。 | | steerReturnTimeSlow | number | 0.55 | 低速回正时间,单位为秒。 | | steerReturnTimeFast | number | 0.4 | 高速回正时间,单位为秒。 | | highSpeedSteerScale | number | 0.3 | 最高车速时的最大转向比例。 |

grip

| 字段 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | maxG | number | 1.2 | 最大侧向加速度,单位为 g。 | | sideFrictionIdle | number | 1 | 直线行驶时侧向摩擦。 | | sideFrictionFrontMin | number | 0.55 | 高负载下前轮侧向摩擦下限。 | | sideFrictionRearMin | number | 0.45 | 高负载下后轮侧向摩擦下限。 | | handbrakeRearFriction | number | 0.35 | 手刹时后轮侧向摩擦。 | | handbrakeRearDriveScale | number | 0.65 | 手刹时后轮驱动力比例。 | | handbrakeReleaseTime | number | 0.15 | 松开手刹后的恢复时间,单位为秒。 | | wheelbaseRatio | number | 0.55 | 轴距相对车长的比例。 |

power

| 字段 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | maxSpeed | number | 100 | 最高速度基准值(km/h,按 scale 缩放)。 | | acceleration | number | 5 | 加速度基准值(m/s²,按 scale 缩放)。 | | deceleration | number | 5 | 制动减速度基准值(m/s²,按 scale 缩放)。 |

反馈

如果你有任何问题或建议,欢迎提交 issue。

致谢