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.4.4

Published

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

Downloads

1,087

Readme

中文 | English

three-player-controller

NPM Package

轻量的第三人称 / 第一人称玩家控制器,开箱即用,基于 three.js 和 three-mesh-bvh 实现人物胶囊体碰撞、BVH 碰撞检测、人物动画、第一/三人称切换与相机避障,利用 three-mesh-bvh 优化碰撞检测性能,大场景下高性能运行。

示例

普通控制

普通控制演示

飞行控制

飞行控制演示

车辆控制

车辆控制演示

移动端控制

移动端控制演示

安装

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

可选依赖

如果需要车辆功能,请额外安装 Rapier:

npm install @dimforge/rapier3d-compat

本地运行

git clone https://github.com/hh-hang/three-player-controller.git
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 { playerController } from "three-player-controller";

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 5000);
const controls = new OrbitControls(camera, renderer.domElement);

const player = new playerController();

await player.init({
    scene,
    camera,
    controls,
    playerModelConfig: {
        url: "./glb/person.glb",
        scale: 0.001,
        idleAnim: "idle",
        walkAnim: "walk",
        runAnim: "run",
        jumpAnim: "jump",
        headBoneName: "Head",
        firstPersonCameraOffset: [0, 10, 20],
    },
    initPos: new THREE.Vector3(0, 0, 0),
});

await player.loadVehicleModel({
    url: "./glb/bugatti.glb",
    position: new THREE.Vector3(22, 3.69, 14.5),
    wheelsNames: ["Wheel_LF", "Wheel_RF", "Wheel_LR", "Wheel_RR"],
    scale: 0.1,
    animations: {
        openDoorAnim: "openDoorLF",
    },
    boardingPoint: new THREE.Vector3(0.5, 0, 1.8),
    seatOffset: new THREE.Vector3(0, 0.6, 0),
    chassisRatio: 0.15,
    suspensionRestLengthRatio: 0.2,
});

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

animate();

API

生命周期

| 方法 | 说明 | | --- | --- | | init(opts, callback?) | 初始化控制器,资源加载完成后执行 callback。 | | update(dt?) | 每帧更新移动、碰撞和动画。 | | destroy() | 销毁控制器并移除事件监听。 | | reset(pos?) | 将角色重置到指定位置或初始位置。 | | switchPlayerModel(model) | 运行时切换角色模型,并保留当前位置和朝向。 | | loadVehicleModel(opts) | 加载车辆,可重复调用加载多辆车。 | | changeView() | 切换第一 / 第三人称视角。 | | setFirstPersonCamera(vertAngle?) | 直接进入第一人称,可指定初始垂直角度。 | | buildStaticCollider(sources?) | 构建静态碰撞体;不传则遍历整个场景。 | | addDynamicCollider(source) | 注册动态碰撞体(如可移动平台)。 | | removeDynamicCollider(source) | 移除已注册的动态碰撞体。 | | clearDynamicColliders() | 移除所有动态碰撞体。 |

状态获取

| 方法 | 返回内容 | | --- | --- | | getPosition() | 当前角色位置。 | | getVelocity() | 当前角色速度,类型为 THREE.Vector3。 | | getIsFirstPerson() | 当前是否为第一人称。 | | getIsFlying() | 当前是否处于飞行模式。 | | getIsOnGround() | 当前是否在地面上。 | | getControllerMode() | 控制模式,0 为人物,1 为车辆。 | | getPlayerModel() | 当前加载的人物模型对象。 | | getPlayerCapsule() | 角色胶囊体网格。 | | getActiveVehicle() | 当前正在使用的车辆实例。 | | getAllVehicles() | 所有已加载车辆实例。 | | getCollider() | 用于 BVH 检测的合并碰撞网格。 | | getCurrentPlayerAnimationName() | 当前播放的动画片段名,没有则返回 null。 | | getCenterScreenRaycastHit() | 屏幕中心射线检测结果,适合做瞄准或交互。 |

输入与运行时控制

| 方法 | 说明 | | --- | --- | | setInput(input) | 注入外部输入状态,适合手柄或自定义按键系统。 | | setMouseSensitivity(v) | 设置鼠标灵敏度。 | | setPlayerScale(v) | 动态修改角色缩放,并同步碰撞相关参数。 | | setPlayerSpeed(v) | 设置移动速度。 | | setPlayerFlySpeed(v) | 设置飞行速度。 | | setJumpHeight(v) | 设置跳跃高度。 | | setGravity(v) | 设置重力。 | | setMinCamDistance(v) | 设置第三人称最小镜头距离。 | | setMaxCamDistance(v) | 设置第三人称最大镜头距离。 | | setThirdMouseMode(v) | 设置第三人称鼠标模式:[0 | 1 | 2 | 3]。 | | setEnableZoom(v) | 设置是否允许镜头缩放。 | | setOverShoulderView(v) | 开关过肩视角偏移。 | | setDebug(v) | 开关碰撞体调试显示。 | | setEnableToward(v) | 开关鼠标驱动的朝向 / 视角更新。 |

动画

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

registerAnimation

player.registerAnimation(key, clipName, {
    loop?: boolean,
    timeScale?: number,
    duration?: number,
    clampWhenFinished?: boolean,
    onFinished?: () => void,
});
  • 当前实现支持 duration,并且会优先于 timeScale 生效。

playAnimation

player.playAnimation(key, {
    fade?: number,
    force?: boolean,
});

registerLocomotionSet

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

事件

player.onAnimationChange = (name, action) => {};
player.onBeforeViewChange = (isFirstPerson) => {};
player.onViewChange = (isFirstPerson) => {};
player.onGroundChange = (onGround) => {};
player.onVehicleEnter = (vehicle) => {};
player.onVehicleExit = (vehicle) => {};
player.onTowardChange = (dx, dy, speed) => {};

| 事件 | 说明 | | --- | --- | | onAnimationChange | 角色当前动画切换时触发。 | | onBeforeViewChange | 第一 / 第三人称切换前触发。 | | onViewChange | 第一 / 第三人称切换后触发。 | | onGroundChange | 落地状态变化时触发。 | | onVehicleEnter | 上车完成后触发。 | | onVehicleExit | 下车完成后触发。 | | onTowardChange | 朝向 / 视角输入更新时触发。 |

全局输入监听辅助函数

import { onAllEvent, offAllEvent } from "three-player-controller";
  • onAllEvent():开启键盘和鼠标输入监听。
  • offAllEvent():关闭键盘和鼠标输入监听。

默认键位

| 按键 | 功能 | | --- | --- | | W / ArrowUp | 前进 | | S / ArrowDown | 后退 | | A / ArrowLeft | 左移 | | D / ArrowRight | 右移 | | Shift | 冲刺 | | Space | 跳跃 | | V | 切换视角 | | F | 切换飞行模式 | | E | 上车 / 下车 | | 鼠标移动 | 控制视角 |

setInput

player.setInput({
    moveX: 1 | 0 | -1,
    moveY: 1 | 0 | -1,
    lookDeltaX: number,
    lookDeltaY: number,
    jump: boolean,
    shift: boolean,
    toggleView: boolean,
    toggleFly: boolean,
    toggleVehicle: boolean,
});

类型定义

PlayerControllerOptions

type PlayerControllerOptions = {
    scene: THREE.Scene;
    camera: THREE.PerspectiveCamera;
    controls: any;
    playerModelConfig: PlayerModelOptions;
    initPos?: THREE.Vector3;
    mouseSensitivity?: number;
    minCamDistance?: number;
    maxCamDistance?: number;
    staticCollider?: THREE.Object3D | THREE.Object3D[];
    dynamicCollider?: THREE.Object3D | THREE.Object3D[];
    isShowMobileControls?: boolean;
    mobileControls?: MobileControlsOptions;
    thirdMouseMode?: 0 | 1 | 2 | 3;
    enableZoom?: boolean;
    enableOverShoulderView?: boolean;
    isFirstPerson?: boolean;
};

PlayerModelOptions

type PlayerModelOptions = {
    url: string;
    scale: number;
    idleAnim: string;
    walkAnim: string;
    runAnim: string;
    jumpAnim: string;
    leftWalkAnim?: string;
    rightWalkAnim?: string;
    backwardAnim?: string;
    flyAnim?: string;
    flyIdleAnim?: string;
    enterCarAnim?: string;
    exitCarAnim?: string;
    gravity?: number;
    jumpHeight?: number;
    speed?: number;
    flySpeed?: number;
    rotateY?: number;
    headBoneName?: string;
    firstPersonCameraOffset?: [number, number, number];
    flyEnabled?: boolean;
    capsuleRadiusRatio?: number;
};

MobileControlsOptions

type MobileControlsOptions = {
    joystick?: boolean;
    jump?: boolean;
    fly?: boolean;
    view?: boolean;
    vehicle?: boolean;
};

VehicleOptions

type VehicleOptions = {
    url: string;
    position: THREE.Vector3;
    wheelsNames: string[];
    scale?: number;
    animations: { openDoorAnim?: string };
    boardingPoint: THREE.Vector3;
    seatOffset?: THREE.Vector3;
    chassisRatio?: number;
    suspensionRestLengthRatio?: number;
    followVehicleDirection?: boolean;
    speedMultiplier?: number;
};

字段说明

PlayerControllerOptions

| 字段 | 类型 | 必填 | 默认值 | 说明 | | --- | --- | --- | --- | --- | | scene | THREE.Scene | 是 | — | three.js 场景实例。 | | camera | THREE.PerspectiveCamera | 是 | — | three.js 相机实例。 | | controls | any | 是 | — | 外部相机控制器,实际通常传入 OrbitControls。 | | playerModelConfig | PlayerModelOptions | 是 | — | 角色模型与角色参数配置。 | | initPos | THREE.Vector3 | 否 | (0, 0, 0) | 初始出生点。 | | mouseSensitivity | number | 否 | 5 | 鼠标灵敏度。 | | minCamDistance | number | 否 | 100 | 第三人称最小镜头距离。 | | maxCamDistance | number | 否 | 440 | 第三人称最大镜头距离。 | | staticCollider | THREE.Object3D \| THREE.Object3D[] | 否 | — | 指定用于生成静态碰撞体的对象;不传则遍历整个场景。 | | dynamicCollider | THREE.Object3D \| THREE.Object3D[] | 否 | — | 初始化时注册的动态碰撞体(如可移动平台)。 | | isShowMobileControls | boolean | 否 | true | 是否在移动端显示虚拟控制 UI。 | | mobileControls | MobileControlsOptions | 否 | 全部显示 | 移动端按钮显隐配置。 | | thirdMouseMode | 0 \| 1 \| 2 \| 3 | 否 | 1 | 第三人称视角下的不同鼠标控制模式,默认1(0:隐藏鼠标控制朝向及视角,1:隐藏鼠标仅控制视角,2:显示鼠标拖拽控制朝向及视角,3:显示鼠标拖拽仅控制视角) | | enableZoom | boolean | 否 | false | 是否允许滚轮缩放。 | | enableOverShoulderView | boolean | 否 | false | 是否启用过肩视角。 | | isFirstPerson | boolean | 否 | false | 初始化时是否直接进入第一人称。 |

PlayerModelOptions

| 字段 | 类型 | 必填 | 默认值 | 说明 | | --- | --- | --- | --- | --- | | url | string | 是 | — | 人物模型路径(GLB/GLTF)。 | | scale | number | 是 | — | 人物模型缩放。 | | idleAnim | string | 是 | — | Idle 动画名,需与模型内动画名一致。 | | walkAnim | string | 是 | — | Walk 动画名,需与模型内动画名一致。 | | runAnim | string | 是 | — | Run 动画名,需与模型内动画名一致。 | | jumpAnim | string | 是 | — | Jump 动画名,需与模型内动画名一致。 | | leftWalkAnim | string | 否 | walkAnim | 左移动画名,不填则复用 walkAnim。 | | rightWalkAnim | string | 否 | walkAnim | 右移动画名,不填则复用 walkAnim。 | | backwardAnim | string | 否 | walkAnim | 后退动画名,不填则复用 walkAnim。 | | flyAnim | string | 否 | idleAnim | 飞行动画名,不填则复用 idleAnim。 | | flyIdleAnim | string | 否 | idleAnim | 飞行待机动画名,不填则复用 idleAnim。 | | enterCarAnim | string | 否 | — | 上车动画名;使用车辆功能时建议配置。 | | exitCarAnim | string | 否 | — | 下车动画名;使用车辆功能时建议配置。 | | gravity | number | 否 | -2400 | 重力基准值,会按角色 scale 缩放。 | | jumpHeight | number | 否 | 600 | 跳跃高度基准值,会按角色 scale 缩放。 | | speed | number | 否 | 300 | 角色移动速度基准值,会按角色 scale 缩放。 | | flySpeed | number | 否 | 2100 | 飞行速度基准值,会按角色 scale 缩放。 | | rotateY | number | 否 | 0 | 模型绕 Y 轴的额外旋转偏移。 | | headBoneName | string | 否 | — | 头部骨骼或节点名称,用于第一人称相机挂载。 | | firstPersonCameraOffset | [number, number, number] | 否 | 有内置默认值 | 第一人称相机局部偏移。若找到 headBoneName,偏移相对头骨骼;否则相对胶囊体。 | | flyEnabled | boolean | 否 | true | 是否允许飞行模式。 | | capsuleRadiusRatio | number | 否 | 1 | 胶囊体半径倍率,用于微调碰撞宽度。 |

MobileControlsOptions

| 字段 | 类型 | 必填 | 默认值 | 说明 | | --- | --- | --- | --- | --- | | joystick | boolean | 否 | true | 是否显示摇杆。 | | jump | boolean | 否 | true | 是否显示跳跃按钮。 | | fly | boolean | 否 | true | 是否显示飞行按钮。 | | view | boolean | 否 | true | 是否显示视角切换按钮。 | | vehicle | boolean | 否 | true | 是否显示上下车按钮。 |

VehicleOptions

| 字段 | 类型 | 必填 | 默认值 | 说明 | | --- | --- | --- | --- | --- | | url | string | 是 | — | 车辆模型路径(GLB/GLTF)。 | | position | THREE.Vector3 | 是 | — | 车辆初始世界坐标。 | | wheelsNames | string[] | 是 | — | 车轮节点名数组,顺序为左前、右前、左后、右后。 | | scale | number | 否 | 1 | 车辆模型缩放。 | | animations.openDoorAnim | string | 否 | — | 车门开关动画名。 | | boardingPoint | THREE.Vector3 | 是 | — | 上车点,局部坐标。 | | seatOffset | THREE.Vector3 | 否 | (0, 0, 0) | 角色上车后座位偏移。 | | chassisRatio | number | 否 | 0.2 | 底盘高度比例。 | | suspensionRestLengthRatio | number | 否 | 0.2 | 悬挂静止长度比例。 | | followVehicleDirection | boolean | 否 | true | 驾驶时镜头是否跟随车辆朝向。 | | speedMultiplier | number | 否 | 1 | 单车速度倍率。 |

反馈

如果你有任何问题或者好的想法欢迎提交issue

致谢

three-mesh-bvh

three