fogón

← BibliotecaObjetomormon/universal-characters

Personajes base universales

m@mormonObjeto, CC0
v1hace 2 días

Obra original de Quaternius ↗

Clonar
FOGONfogon pieces add universal-characters
GITgit clone https://git.fogon.gg/mormon/universal-characters.git
REMIXfogon new universal-characters --from universal-characters
ZIPuniversal-characters.zipBajar
Controles

Personajes base universales

Los Universal Base Characters de Quaternius listos para three.js: un hombre y una mujer (en ropa interior: para vestirlos, o para usarlos así), cinco peinados, cejas y barba, y colores para la piel, el pelo, los ojos y la ropa interior. Traen el esqueleto de 65 huesos de la Universal Animation Library: cualquier animación de esa biblioteca los mueve.

El armador de la demo

En la demo armás uno con los controles (o tocás uno ya armado, o «al azar»), elegís la animación, y abajo aparece la línea de código que lo crea: un clic y la copiás. «Varios» pone siete juntos.

Qué trae

  • 2 cuerpos: hombre (1,81 m, 13.334 triángulos) y mujer (1,77 m, 13.580), con ojos aparte.
  • 5 peinados: rapado (sin pelo), corto, con raya, largo y rodetes. Todos van en los dos cuerpos.
  • Cejas (las de cada cuerpo) y barba.
  • 9 pieles (pálida, clara, media, morena, marrón, oscura, y verde, azul y gris para orcos y otros), 8 colores de pelo, 5 de ojos, 7 de ropa interior. La piel, el pelo y la ropa interior aceptan también cualquier "#rrggbb".
  • 12 animaciones de muestra (para que la demo se mueva y para empezar): quieto, hablando, caminar, trotar, correr, salto (arranque, en el aire, caída), bailar, un gesto con la mano, sentado y un golpe. Las demás van en la pieza universal-animations.
  • Todo pesa ~2 MB: modelos 0,56 MB y animaciones 0,62 MB (comprimidos con meshopt), 16 texturas WebP 0,8 MB.

Usarlo en tu juego

fogon pieces add universal-characters

Eso trae client/universal-characters/characters.ts (solo código: los modelos se cargan de la demo publicada en https://play.fogon.page/universal-characters/characters/, que los sirve a cualquier juego). Necesita three.

import * as THREE from "three";
import { loadCharacters, createCharacter, randomLook } from "./universal-characters/characters";

await loadCharacters(); // una vez

const hero = createCharacter({ body: "female", skin: "tan", hair: "buns", hairColor: "black", eyes: "hazel", underwear: "red" });
scene.add(hero.object);
hero.play("Walk_Loop");

const stranger = createCharacter(randomLook());
stranger.object.position.set(2, 0, 0);
scene.add(stranger.object);

// en el bucle del juego, con los segundos desde el cuadro anterior:
hero.update(dt);
stranger.update(dt);

// una animación que se juega una vez y vuelve a esperar:
hero.play("Punch_Jab", { loop: false, onEnd: () => hero.play("Idle_Loop") });

// algo en la mano (va con el hueso):
hero.attach(sword, "hand_r");

Lo que exporta el módulo:

loadCharacters({ base?, clips?, onProgress?, manager?, anisotropy? })Carga el kit (una vez). clips: false no trae las animaciones de muestra. Devuelve un CharacterKit.
createCharacter(look?, { clip? })Un personaje (lo que falte del look sale de DEFAULT_LOOK). Arranca con Idle_Loop; clip: null lo deja en su pose de reposo.
Characterobject (lo que va a la escena: mira a +Z, pies en y = 0), skeleton, bones (por nombre), bone(nombre), mixer, action, play(clip, { loop, fade, speed, from, fit, onEnd }), stop(), update(dt), attach(objeto, hueso = "hand_r"), clips, clip, look, body, pieces, triangles, height, dispose().
CharacterKitcreate(look?, opciones?), clips (un Map por nombre), addClips(clips), fit(clip, cuerpo), catalog, base, dispose().
randomLook(rand?)Un look al azar (con una función rand con semilla, siempre el mismo).
BODIES, SKINS, HAIRS, HAIR_COLORS, EYES, UNDERWEARLas opciones, con su nombre en castellano para mostrar (y su color).
DEFAULT_LOOK, fullLook(), BONES, DEFAULT_BASEEl look de partida, completar uno, los 65 huesos, de dónde se cargan los archivos.

El look

CampoValores
body"male", "female"
skin"pale", "light", "medium", "tan", "brown", "dark", "green", "blue", "grey" o "#rrggbb"
hair"none", "buzzed", "parted", "long", "buns"
hairColor"black", "brown", "blond", "red", "grey", "white", "pink", "blue" o "#rrggbb" (pelo, cejas y barba)
eyebrowstrue / false
beardtrue / false
eyes"brown", "hazel", "green", "blue", "grey"
underwear"black", "white", "red", "blue", "green", "yellow", "purple" o "#rrggbb"

El color de piel es el que queda (no un tinte encima): la textura conserva su sombreado y toma el tono pedido. La ropa interior tiene su color aparte, así que cambiar la piel no la cambia.

Muchos personajes salen baratos: la geometría es de todos, y los materiales se arman una vez por color (una multitud con cinco tonos de piel tiene cinco materiales de piel). Lo propio de cada uno es su esqueleto y su mixer.

El esqueleto

65 huesos, los de la Universal Animation Library (los nombres de Unreal). Están en BONES, y en cada personaje en character.bones / character.bone("hand_r"):

  • Tronco: root, pelvis, spine_01, spine_02, spine_03, neck_01, Head (con mayúscula).
  • Brazos (_l y _r): clavicle, upperarm, lowerarm, hand.
  • Dedos (_l y _r): thumb, index, middle, ring, pinky, cada uno _01, _02, _03 y _04_leaf (por ejemplo index_02_l, thumb_04_leaf_r).
  • Piernas (_l y _r): thigh, calf, foot, ball, ball_leaf.

Sumarle las animaciones de universal-animations

Esta pieza trae doce animaciones de muestra. La biblioteca entera (pelea, armas, nadar, trepar, zombi…) está en la pieza universal-animations, hecha para este mismo esqueleto. Sus clips son THREE.AnimationClip con pistas por nombre de hueso (pelvis.quaternion, hand_r.quaternion…), así que entran directo:

import { loadAnimations, clipNames, clipNow } from "./universal-animations/animations"; // fogon pieces add universal-animations

const kit = await loadCharacters({ clips: false }); // sin las de muestra, si vas a traer las otras

await loadAnimations(); // los dos packs (o loadAnimations("ual1") para uno solo)
const clips: THREE.AnimationClip[] = clipNames().map((name) => clipNow(name));

// 1) dárselos al kit: desde ahí cualquier personaje los juega por nombre
kit.addClips(clips);
hero.play("Zombie_Idle_Loop");

// 2) o pasarle el clip a play()
hero.play(clips[0], { loop: false });

// 3) o usar el mixer a mano, como con cualquier modelo de three.js
hero.mixer.clipAction(clips[0]).play();

**La diferencia entre play() y el mixer a mano.** Las animaciones de la biblioteca están hechas sobre un maniquí cuyos huesos no miden lo mismo que los de estos cuerpos ni descansan en los mismos ángulos. Con mixer.clipAction(clip) el clip funciona tal cual viene, pero como mueve los 65 huesos (posición incluida), le da al cuerpo las proporciones del maniquí: hombros más anchos, la mujer igual de alta que el hombre. play() primero ajusta el clip al cuerpo (la misma pose con los huesos propios; se hace una vez por clip y por cuerpo y tarda unos milisegundos) y es lo que conviene usar. play(clip, { fit: false }) lo juega sin ajustar, y kit.fit(clip, "female") devuelve el clip ajustado para usarlo con tu propio mixer.

Usar los archivos sin internet

Los modelos y texturas están en public/characters/ de esta pieza (fogon pieces add trae solo el código). Copiá esa carpeta al public/ de tu juego y cargá desde ahí:

await loadCharacters({ base: "./characters/" });
Archivo
characters.glbLos dos cuerpos con su esqueleto y las ocho piezas de cabeza (meshopt).
anims.glbLas doce animaciones de muestra, sobre el esqueleto del maniquí, sin malla.
catalog.jsonMedidas de cuerpos y piezas, huesos, animaciones y la pose de reposo del maniquí (lo que usa el ajuste).
textures/Piel (color, normal, y máscara de ropa interior + rugosidad), pelo (2 juegos), ojos (5 colores).

tools/build.ts es el script que arma todo eso desde los dos zips de Quaternius (no se publica con la pieza; sus dependencias están en tools/package.json):

cd tools && bun install
bun build.ts "<carpeta de Universal Base Characters>" "<carpeta de Universal Animation Library>"

Cómo está hecho

  • El pelo, las cejas y la barba. El pack los trae de dos maneras: «Origin at 0» (la malla suelta, en el origen) y «Rigged to Head Bone» (con el esqueleto, pesada entera al hueso Head). Se usó la segunda: dice sobre qué cuerpo se modeló cada pieza y dónde va, y como cada vértice sigue a un solo hueso, se le saca el esqueleto y queda una malla común colgada del hueso Head: sigue a la cabeza en cualquier animación sin el costo de una malla con huesos. Para ponerla en el otro cuerpo se corre lo que difieren los dos cráneos (miden lo mismo; cambian unos milímetros de lugar).
  • Los colores. El pack trae la piel en dos versiones que solo cambian la ropa interior. De la diferencia sale una máscara: el material pinta la piel de un color y la ropa interior de otro. Los ojos de color son la textura original (marrón) con el iris repintado.
  • Lo que no se cambió: las mallas, los pesos y las proporciones son los de Quaternius.

Límites

  • Vienen en ropa interior y no hay ropa en esta pieza: es la base para vestir (lo que se agregue tiene que estar pesado a este mismo esqueleto) o para usar tal cual.
  • Las cejas de cada cuerpo son las suyas (las de uno no calzan en la cara del otro), y la barba se modeló sobre el hombre: en la mujer queda en su lugar, pero es la misma barba.
  • No hay huesos en la cara: los ojos y la boca no se mueven.
  • Las animaciones no desplazan al personaje (sin «root motion»): para que camine, movés object.position vos (Walk_Loop anda bien a ~1 m/s).
  • En la biblioteca de animaciones no hay un saludo con la mano: la muestra trae Interact (un gesto con la mano) e Idle_Talking_Loop.
  • Los colores de ojos son cinco, fijos (son texturas); la piel, el pelo y la ropa interior sí aceptan cualquier color.

Créditos y licencia

Modelos, texturas y animaciones de Quaternius: Universal Base Characters (cuerpos, peinados, cejas y barba) y Universal Animation Library (las doce animaciones de muestra). Todo es CC0: usalo como quieras, también en juegos comerciales, sin pedir permiso ni citar (aunque nombrar a Quaternius está lindo).