Component·three·v1.0.0·MIT

Gltf Character Controller

Loads a GLTF/GLB model, exposes named animations, and drives WASD movement with smooth turning. Three.js component for vanilla scenes.

#three#character#gltf#controller

Install

npx gamecn add gltf-character-controller

Usage

ts
import { GltfCharacterController } from '@/components/GltfCharacterController';
const character = await GltfCharacterController.load('/models/hero.glb');
scene.add(character.object);
character.play('idle');
// In your render loop:
character.update(dt, input.axis('left','right','up','down'));

Source preview

Compatibility

Engines
three >=0.160.0
Frameworksvanilla
Languagestypescript
Bundlersvite

Files installed

  • {components}/GltfCharacterController.ts
  • docs/gamecn/gltf-character-controller.md(docs)

Dependencies

npm

three@>=0.160.0

Notes

Usage

import { GltfCharacterController } from "@/components/GltfCharacterController";
import { OrbitScene } from "@/scenes/OrbitScene"; // pair with @main/orbit-scene
import { InputManager } from "@/utilities/InputManager";

const orbit = new OrbitScene({ canvas, shadows: true });

const character = await GltfCharacterController.load("/models/hero.glb", {
  speed: 4,
  turnSpeed: 6,
});
orbit.scene.add(character.object);

console.log("animations:", character.animationNames());
character.play("idle");

const input = new InputManager({
  bindings: {
    left: ["KeyA", "ArrowLeft"],
    right: ["KeyD", "ArrowRight"],
    up: ["KeyW", "ArrowUp"],
    down: ["KeyS", "ArrowDown"],
  },
});

orbit.onUpdate((dt) => {
  const axis = input.axis("left", "right", "up", "down");
  character.update(dt, axis);
  character.play(Math.hypot(axis.x, axis.y) > 0.1 ? "run" : "idle");
  input.endFrame();
});

orbit.start();

Options

Option Default Description
speed 4 Movement speed (units/sec).
turnSpeed 4 Turns/sec the model rotates toward movement direction.
scale 1 Multiplied into the loaded GLTF scale.

API

Method Description
static load(url, opts?) Async-load a GLTF and return a controller.
play(name, fadeSec?) Cross-fade to a named animation.
animationNames() List baked clip names.
update(dt, axis) Per-frame; pass delta-seconds + 2D axis.

Notes

  • The controller doesn't ship with art. Bring a GLTF/GLB with named clips (idle, run, …). Mixamo + the Mixamo→GLTF converter is a good source for prototyping.
  • For scenes lit by @main/orbit-scene, pass shadows: true to that scene and set castShadow/receiveShadow on your meshes.