# BVHEcctrl **Repository Path**: mirrors_pmndrs/BVHEcctrl ## Basic Information - **Project Name**: BVHEcctrl - **Description**: A simple R3f character controller - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-06-25 - **Last Updated**: 2026-02-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 🕹️ BVHEcctrl [![Demo Preview](public/images/BVHControllerP1-封面.jpg)](https://bvhecctrl.vercel.app/) [**BVHEcctrl**](https://github.com/pmndrs/bvhecctrl) is a lightweight, plug-and-play character controller designed for [`react-three-fiber`](https://github.com/pmndrs/react-three-fiber). It requires **no physics engine**, and utilizes [`three-mesh-bvh`](https://github.com/gkjohnson/three-mesh-bvh) for highly efficient, triangle-accurate collision detection and response. > 🧠 Ideal for web-based 3D experiences such as games, interactive portfolios, and virtual worlds. --- ## 📸 Examples

Demo 1 Demo 2

--- ## ✨ Features - No physics engine required - Fast BVH-based collision detection - Smooth floating capsule movement for stairs, slopes, and uneven surfaces - Built-in support for: - `StaticCollider` - `KinematicCollider` - `InstancedStaticCollider` --- ## 📦 Installation ```bash npm install bvhecctrl ``` ## ⚙️ How to Use ### Step 1: Setup Keyboard Controls and Character Controller ```js import BVHEcctrl from "bvhecctrl"; import { KeyboardControls } from "@react-three/drei"; const keyboardMap = [ { name: "forward", keys: ["ArrowUp", "KeyW"] }, { name: "backward", keys: ["ArrowDown", "KeyS"] }, { name: "leftward", keys: ["ArrowLeft", "KeyA"] }, { name: "rightward", keys: ["ArrowRight", "KeyD"] }, { name: "jump", keys: ["Space"] }, { name: "run", keys: ["Shift"] }, ]; return ( ); ``` ### Step 2: Add Colliders to Your Map ```js import { StaticCollider, KinematicCollider, InstancedStaticCollider, } from "bvhecctrl"; useFrame((_, delta) => { if (kinematicRef.current) kinematicRef.current.rotation.y += delta; }); return ( <> ); ``` ### Step 3: Handle Camera Movement You can use any camera control system that fits your needs — such as ``, ``, ``, or your own custom setup. For smooth and flexible control, I highly recommend using [``](https://github.com/yomotsu/camera-controls) from [`@react-three/drei`](https://github.com/pmndrs/drei). It even offers built-in camera collision support. Here’s a simple example using `` to follow the character: ```js useFrame(() => { camControlRef.current.moveTo( ecctrlRef.current.group.position.x, ecctrlRef.current.group.position.y + 0.3, ecctrlRef.current.group.position.z, true ); }); ``` ## 🧱 BVHEcctrl Props | Prop | Type | Default | Description | | ---------------------------- | ---------------------------------------- | ------------------ | ------------------------------------------------------------- | | `debug` | `boolean` | `false` | Enables visual debugging. | | `colliderCapsuleArgs` | `[number, number, number, number]` | `[0.3, 0.6, 4, 8]` | Capsule shape: [radius, height, capSegments, radialSegments]. | | `paused` | `boolean` | `false` | Freezes character physics and collision response. | | `delay` | `number` | `1.5` | Physics delay after initialization (in seconds). | | `gravity` | `number` | `9.81` | World gravity. | | `fallGravityFactor` | `number` | `4` | Multiplier to increase falling speed. | | `maxFallSpeed` | `number` | `50` | Maximum fall velocity cap. | | `mass` | `number` | `1` | Virtual mass, affects float behavior. | | `sleepTimeout` | `number` | `10` | Time before character enters sleep state when idle. | | `slowMotionFactor` | `number` | `1` | Global time scaling (e.g., `0.5` = half-speed). | | `turnSpeed` | `number` | `15` | Turn speed when changing direction. | | `maxWalkSpeed` | `number` | `3` | Max speed when walking. | | `maxRunSpeed` | `number` | `5` | Max speed when running. | | `acceleration` | `number` | `30` | Speed increase per second. | | `deceleration` | `number` | `20` | Speed decrease when input is released. | | `counterAccFactor` | `number` | `0.5` | Extra acceleration multiplier when changing direction. | | `airDragFactor` | `number` | `0.3` | Simulated drag while in air. | | `jumpVel` | `number` | `5` | Upward velocity when jumping. | | `floatCheckType` | `"RAYCAST"` \| `"SHAPECAST"` \| `"BOTH"` | `BOTH` | Able to switch between different float check type. | | `maxSlope` | `number` | `1` | Max walkable surface slope (in radians). | | `floatHeight` | `number` | `0.2` | Desired float height above ground. | | `floatPullBackHeight` | `number` | `0.25` | Additional distance below ground used to pull character down. | | `floatSensorRadius` | `number` | `0.12` | Radius of the sensor used to sense the ground. | | `floatSpringK` | `number` | `600` | Spring constant for floating. | | `floatDampingC` | `number` | `28` | Damping factor for float spring (prevents oscillation). | | `collisionCheckIteration` | `number` | `3` | Number of collision check per frame. | | `collisionPushBackVelocity` | `number` | `3` | Extra velocity applied to resolve penetration. | | `collisionPushBackDamping` | `number` | `0.1` | Damping applied to the pushback force. | | `collisionPushBackThreshold` | `number` | `0.005` | Minimum depth before pushback activates. | ## 🧱 Collider Component Props | Prop | Type | Default | Description | | ----------------------- | --------- | ------------- | ------------------------------------------------------------ | | `debug` | `boolean` | `false` | Shows BVH bounds for debugging. | | `debugVisualizeDepth` | `number` | `10` | Depth level of BVH to visualize (debug only). | | `restitution` | `number` | `0.05` | Bounciness on impact. | | `friction` | `number` | `0.8` | Surface friction against character movement. | | `excludeFloatHit` | `boolean` | `false` | If true, this collider is ignored in float sensor checks. | | `excludeCollisionCheck` | `boolean` | `false` | If true, this collider is excluded from collision detection. | | `BVHOptions` | `object` | _(see below)_ | Configuration for building the internal BVH tree. | Default BVHOptions: ```js { strategy: SAH, verbose: false, setBoundingBox: true, maxDepth: 40, maxLeafTris: 10, indirect: false } ``` ## 🎮 Virtual Joystick and Button Integration BVHEcctrl provides mobile-friendly UI components to control character movement and actions using touch input. Simply import and place `` and `` outside the `` component: ```js import { Joystick, VirtualButton } from "bvhecctrl"; ``` You can define additional components beyond the built-in "run" and "jump" ones, such as: ```js import { VirtualButton, useButtonStore } from "bvhecctrl"; ; // Later access it in your logic const { buttons } = useButtonStore.getState(); console.log(buttons.dance); // true or false ``` ## 🧱 Joystick Component Props | Prop | Type | Default | Description | | ---------------------- | --------------------- | ------- | --------------------------------- | | `joystickMaxRadius` | `number` | `50` | Maximum drag radius. | | `joystickWrapperStyle` | `React.CSSProperties` | `-` | CSS style for the outer wrapper. | | `joystickBaseStyle` | `React.CSSProperties` | `-` | CSS style for the joystick base. | | `joystickKnobStyle` | `React.CSSProperties` | `-` | CSS style for the draggable knob. | ## 🧱 VirtualButton Component Props | Prop | Type | Default | Description | | -------------------- | --------------------- | ------- | --------------------------------------------------------- | | `id` | `string` | `-` | Unique ID to map to actions ("run" & "jump" are handled). | | `label` | `string` | `-` | Optional label text on the button. | | `buttonWrapperStyle` | `React.CSSProperties` | `-` | CSS style for the wrapper container. | | `buttonCapStyle` | `React.CSSProperties` | `-` | CSS style for the button cap. | ## 🧩 Extra Utilities ### Accessing the Controller Ref: ```js // Access the character group (THREE.Group) ecctrlRef.current.group; // Access the character model (THREE.Group) ecctrlRef.current.model; // Reset current velocity to zero ecctrlRef.current.resetLinVel(); // Add linear velocity directly ecctrlRef.current.addLinVel(THREE.Vector3); // Set linear velocity directly ecctrlRef.current.setLinVel(THREE.Vector3); // Set character movement, can have one or more inputs ecctrlRef.current.setMovement({ forward: boolean, backward: boolean, leftward: boolean, rightward: boolean, joystick: { x: number; y: number }, run: boolean, jump: boolean, }); ``` ### Read-only Character Status: ```js import { characterStatus } from "bvhecctrl"; characterStatus.position; // THREE.Vector3 characterStatus.linvel; // THREE.Vector3 characterStatus.quaternion; // THREE.Quaternion characterStatus.inputDir; // THREE.Vector3 characterStatus.movingDir; // THREE.Vector3 characterStatus.isOnGround; // boolean characterStatus.isOnMovingPlatform; // boolean characterStatus.animationStatus; // "IDLE" | "WALK" | "RUN" | "JUMP_START" | "JUMP_IDLE" | "JUMP_FALL" | "JUMP_LAND" ``` ### Accessing Character Animation Status (global store) ```js // You can track the current animation state of the character using the global animation store import { useAnimationStore } from "bvhecctrl"; const animationStatus = useAnimationStore((state) => state.animationStatus); // "IDLE" | "WALK" | "RUN" | "JUMP_START" | "JUMP_IDLE" | "JUMP_FALL" | "JUMP_LAND" // This value updates reactively and can be used in a useEffect: useEffect(() => { console.log("Animation changed to:", animationStatus); }, [animationStatus]); ``` ## 💰 Support This Project If you find **BVHEcctrl** helpful, please consider [supporting the project](https://github.com/sponsors/ErdongChen-Andrew). Your support means a lot and will help me dedicate more time to development, improvements, and documentation. Every bit of support helps! Whether it’s a donation, a star, or simply sharing the project. Thank you for helping me keep this project moving forward! 🙏 ## 💡 What Add-ons Would You Like to See? I’m considering offering additional features or paid extensions. If you're interested, feel free to vote or leave feedback: - A vanilla three.js version of BVHEcctrl - Custom gravity support (move on spheres) - Tutorials on building this controller from scratch - More experimental features and playground demos 💬 **Leave your thoughts on [GitHub](https://github.com/pmndrs/BVHEcctrl/issues) or join the discussion on the [pmndrs Discord](https://discord.com/channels/740090768164651008/1162488856088690879).**