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

meshwalk

v1.4.0

Published

MeshWalk.js is a lightweight character controller library for three.js game development.

Readme

MeshWalk.js

MeshWalk.js is a lightweight character controller library for three.js game development.

examples

Usage and Examples

See the following demos and check the source code, which includes comments explaining each feature. (Requires three.js, installed via peer dependencies or loaded with an import map.)

  1. get started
  2. keyboard Input
  3. the CameraControl
  4. objects
  5. terrain
  6. AnimationController
  7. all together
  8. remove collider
  9. moving platform
  10. ladder

examples with recast-navigation-js:

Getting started

npm install three meshwalk
import * as THREE from 'three';
import * as MW from 'meshwalk';

const world = new MW.World();

// Bake the level geometry into a collider (a snapshot of its world transform)
const level = MW.StaticBody.fromObject( levelMesh );
world.add( level );

const player = new MW.CharacterController( { radius: 0.5, height: 2 } );
player.teleport( new THREE.Vector3( 0, 10, 0 ) );
world.add( player );

const timer = new THREE.Timer();
timer.connect( document );

( function update() {

	requestAnimationFrame( update );
	timer.update();
	const delta = timer.getDelta();

	player.move( desiredHorizontalVelocity ); // a THREE.Vector3, in m/s
	world.update( delta );

	// The engine never touches your scene graph -- copy the transform yourself
	playerMesh.position.copy( player.position );
	playerMesh.quaternion.copy( player.quaternion );

	renderer.render( scene, camera );

} )();

Units are meters and seconds. world.update( delta ) accepts a real frame delta and runs the simulation on a fixed step internally, so behavior does not depend on the frame rate.

API

World( { fps = 60, stepsPerFrame = 4 } )

| member | description | |---|---| | add( body ) | Register a StaticBody, KinematicBody, CharacterController or ClimbableBody. | | remove( body ) | Unregister it. | | update( deltaTime ) | Advance by a real delta (seconds). Accumulates into fixed steps of 1 / fps, catching up at most 5 frames' worth at once so a long stall cannot spiral. | | fixedUpdate() | Advance exactly one fixed step. Deterministic, useful for tests. | | colliders | Read only list of the registered StaticBody / KinematicBody. | | dispose() | Dispose every registered body and drop the references. |

StaticBody

The static environment collider: a triangle mesh that never moves, baked into an internal octree.

| member | description | |---|---| | StaticBody.fromObject( object3D ) | Create from an Object3D, walking its descendants and taking every Mesh in world space. | | addFromObject( object3D ) | Same, additive. | | addFromGeometry( geometry, matrix? ) | Take a BufferGeometry directly, optionally transformed. | | addTriangles( positions, indices? ) | Take already baked world-space flat xyz positions and optional triangle indices directly. | | dispose() | Drop the baked triangles. |

Geometry is snapshotted at the time it is added, so moving the source Object3D afterwards does not move the collider. Use KinematicBody for geometry that moves.

KinematicBody

A velocity driven moving platform: elevators, sliding and rotating floors, conveyor belts. The shape is baked once in local space; the body is moved by writing its velocities.

| member | description | |---|---| | KinematicBody.fromBox( { width, height, depth } ) | Shorthand for a box shaped platform, centered on the origin. | | KinematicBody.fromObject( object3D ) | Create from an Object3D, taking every Mesh in the object's own local space. | | addFromObject( object3D ) / addFromGeometry( geometry, matrix? ) | Additive variants. | | position, quaternion | Current transform. Writing position directly teleports the platform without dragging its riders. | | velocity | World space translation, m/s. | | angularVelocity | Rotation around the body origin, rad/s: direction is the axis, length is the speed (yaw is ( 0, ω, 0 )). | | surfaceVelocity | Surface flow, m/s: the platform stays still and only carries whoever stands on it (a conveyor belt). | | dispose() | Drop the baked triangles. |

Motion policy stays on your side: read position each frame and flip velocity when you want the platform to turn around. A character standing on the platform is carried, keeps its orbit on a rotating floor, and inherits the horizontal velocity when it leaves (jumping off, or walking off the edge).

CharacterController( options )

| option | default | description | |---|---|---| | radius | required | Capsule radius. | | height | required | Total capsule height, tip to tip (clamped to at least radius * 2). | | slopeLimit | 50 | Degrees. Anything steeper cannot be walked up and slides down. | | stepOffset | 0.3 | Steps up to this height are climbed automatically. 0 disables it. | | groundCheckDepth | 0.3 | How far below the feet still counts as grounded, so the character walks down small steps instead of falling. | | landingLockDuration | 0.2 | Seconds of input lock after landing from a jump or a fall. | | jumpDuration | 1 | Total length of the jump arc in seconds. Larger jumps higher and longer. |

| member | description | |---|---| | move( vector3 ) | Desired horizontal velocity in world space, m/s. The y component is ignored (gravity, jumping and ground snapping own the vertical axis). It persists until the next call, so pass a zero vector to stop. | | jump() | Start a jump. Ignored while landing, already jumping, airborne or sliding. While climbing it pops off the surface instead. | | climb( vector2 ) | Climbing input while attached to a ClimbableBody: x is sideways, y is up. Camera independent, so forward always means up. | | teleport( vector3 ) | Move instantly, clearing the landing lock and any climbing state. | | position, quaternion | The result of the simulation. Copy them onto your mesh after world.update(). | | velocity | The final velocity the engine produced this step. This is an output, not an input -- use move() to drive the character. | | isGrounded, isOnSlope, isIdling, isRunning, isJumping, isLanding, isClimbing | State flags. | | groundHeight, groundNormal, groundBody | The floor under the character. groundBody is the owning body, so it is a KinematicBody while riding a moving platform. | | slopeLimit, stepOffset, groundCheckDepth, landingLockDuration, jumpDuration | The options above, writable at runtime. | | carryRotation | When true (default), a rider turns with the yaw of a rotating platform. | | dispose() | Drop internal references. |

Events: startIdling, startWalking, startJumping, startSliding, startFalling, startLanding, endLanding, startClimbing, endClimbing.

player.addEventListener( 'startWalking', () => animationController.play( 'run' ) );

ClimbableBody( { mode, box, faceDirection, speed } )

A zone the character can climb -- a ladder. It is not a collider, it only marks where climbing is allowed; the ladder you see is your own mesh and does not need to be part of a collider at all.

| option | default | description | |---|---|---| | mode | required | 'ladder'. 'free' (climbing any wall inside the zone) is declared but not implemented yet. | | box | required | THREE.Box3 in world space. | | faceDirection | ( 0, 0, 1 ) | Horizontal direction the ladder faces, i.e. the side the player approaches from. | | speed | 3 | Climbing speed, m/s. |

The character attaches by pushing into the ladder from below or from the side, by pushing off the edge while standing on top of it (so walking off the edge continues into climbing down), or by grabbing it in mid air while jumping or falling. It mantles onto the top at the upper end, steps off at the lower end, and jump() pushes it away from the surface.

KeyboardControls

WASD, the arrow keys and space, listening on window. Keystrokes typed into a form field are ignored, and holding a key while the window loses focus does not stick.

| member | description | |---|---| | inputVector | THREE.Vector2, x is right, y is forward. Normalized, zero length when nothing is pressed. | | jump() | Dispatch jumpkeypress manually (for an on screen button). | | dispose() | Remove the listeners. |

Events: movekeyon, movekeychange, movekeyoff, jumpkeypress.

The input is camera independent by design -- rotate it into world space yourself:

const input = keyboardControls.inputVector;
player.move(
	moveDir.set( input.x, 0, - input.y )
		.applyAxisAngle( yAxis, cameraControls.frontAngle )
		.multiplyScalar( 10 ) // speed, m/s
);

ThirdPersonCameraControls( camera, trackObject, world, domElement, character? )

A camera-controls subclass that follows trackObject and keeps the level geometry registered in world out of the way, so the whole camera-controls API is available on it.

| member | description | |---|---| | frontAngle | The current azimuth angle. Rotate your input by this to get camera relative movement. | | syncFrontAngleToPlatform | When true (default) and a character was passed, the azimuth follows the yaw of the rotating platform the character rides, keeping the over the shoulder view fixed relative to the platform. |

AnimationController( mesh, animationClips )

A thin AnimationMixer wrapper that cross fades between clips.

| member | description | |---|---| | actions | The AnimationAction per clip name, so you can set loop modes and weights. | | play( name ) | Cross fade to that clip (0.3s). A no-op if it is already playing. | | turn( radians, immediate ) | Turn the mesh towards an angle. | | update( deltaTime ) | Advance the mixer. Call it every frame. | | dispose() | Stop everything and uncache the root. |