Your avatar, as a character in your own game
Turn a photo into a 3D avatar on Generato, download it, and drop it into any three.js game, simulation or WebXR app. It walks, runs, waves and dances with 161 free animations, using a 29 KB loader.
Live demo running on the SDK. Pick an animation, or drop the ZIP you downloaded from Generato onto it. Your file stays on your device.
How it works
- Make an avatar on Generato from a photo or a text prompt, and make it animatable (rigging is automatic).
- Download it from your library and pick a format. For the web you get a ZIP with the avatar (a 3D Gaussian splat), its skeleton and a README. For Unity and VRChat you get an FBX, and for Blender, Godot, Unreal and web engines a GLB: the same standard rigged mesh (see Game engines). Downloads come with any plan.
- Put the files next to your page, keeping them in one folder:
rig.json,weights.binand the.ply. - Load it with the code below, then play any animation by name.
Quick start
One HTML file, no build step. three.js and Spark (the splat renderer) come from a CDN, and the SDK from generato.io.
<!doctype html>
<html>
<body style="margin:0">
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.180.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.180.0/examples/jsm/",
"@sparkjsdev/spark": "https://cdn.jsdelivr.net/npm/@sparkjsdev/spark@2.4.0/dist/spark.module.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { GeneratoAvatar } from 'https://generato.io/sdk/generato-avatar.js';
const renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 0.05, 100);
camera.position.set(0, 1.4, 3.6);
camera.lookAt(0, 0.9, 0);
// The rig.json from your ZIP; weights.bin and the .ply sit next to it.
const avatar = await GeneratoAvatar.load({ url: './my-avatar/rig.json', renderer, scene });
scene.add(avatar.object);
avatar.play('walk');
const clock = new THREE.Clock();
renderer.setAnimationLoop(() => {
avatar.update(clock.getDelta());
renderer.render(scene, camera);
});
</script>
</body>
</html>Serve the page over http(s) (for example npx serve), not as a file:// page, so the browser can fetch the avatar files. Keep the three/addons/ line: Spark needs it.
With a bundler (Vite, webpack, Next.js)
Install three.js and the exact Spark version, then save generato-avatar.js into your project and import it like any other module. An npm package is on the way.
npm install three@^0.180.0 @sparkjsdev/spark@2.4.0import { GeneratoAvatar } from './generato-avatar.js';Examples
Each example is one HTML file. Open it and view the page source to copy it.
Third-person character
Walk and run with WASD or a touch joystick, with a follow camera. The avatar switches between idle, walk and jog by itself.
Play itBasic scene
The smallest working scene: orbit camera, one avatar, double-click to change the animation.
OpenMove it like a game character
Walks and runs play on the spot by default, so your game decides where the character goes. Move and turn avatar.object yourself, and switch the animation when the speed changes:
// Each frame: dir is the direction you want to move in (a THREE.Vector3), running is a boolean.
const moving = dir.lengthSq() > 0;
const want = !moving ? 'idle' : running ? 'jog' : 'walk';
if (avatar.animation !== want) avatar.play(want); // crossfades for you
if (moving) {
dir.normalize();
avatar.object.rotation.y = Math.atan2(dir.x, dir.z); // the avatar faces +Z
avatar.object.position.addScaledVector(dir, (running ? 3.6 : 1.4) * dt);
}
avatar.update(dt);WebXR (Meta Quest, Vision Pro, phones)
The avatar is a normal three.js object, so WebXR works the usual way. Place it in front of the viewer:
import { VRButton } from 'three/addons/webxr/VRButton.js';
renderer.xr.enabled = true;
document.body.appendChild(VRButton.createButton(renderer));
avatar.object.position.set(0, 0, -1.5);
avatar.object.rotation.y = 0; // already faces the viewer (+Z)React Three Fiber
Load it once and hand the object to <primitive>:
import { useEffect, useState } from 'react';
import { useThree, useFrame } from '@react-three/fiber';
import { GeneratoAvatar } from './generato-avatar.js';
export function Avatar({ url, animation = 'idle' }) {
const { gl, scene } = useThree();
const [avatar, setAvatar] = useState(null);
useEffect(() => {
let current;
GeneratoAvatar.load({ url, renderer: gl, scene }).then((a) => { current = a; setAvatar(a); });
return () => current?.dispose();
}, [url, gl, scene]);
useEffect(() => { avatar?.play(animation); }, [avatar, animation]);
useFrame((_, dt) => avatar?.update(dt));
return avatar ? <primitive object={avatar.object} /> : null;
}Animations
Every avatar can play all of these. Click a name to copy it, then call avatar.play('name'). They load on demand from generato.io and are free to use (CC0, from Mesh2Motion).
Loading the list…
API
| Call | What it does |
|---|---|
await GeneratoAvatar.load({ url, renderer, scene }) | Loads an avatar from its rig.json URL. Options: height (metres, default 1.7), onProgress(loaded, total), animations (your own copy of the animation library). |
await GeneratoAvatar.load({ files, renderer, scene }) | Loads from memory: files = { rig, weights, splat } (rig as an object, the other two as bytes), for example from a ZIP the user picked. |
avatar.object | The three.js object to add to your scene. Its origin is between the feet, and it faces +Z. |
avatar.play(name) | Plays an animation, crossfading from the current one. A one-shot animation returns to the loop it interrupted. |
avatar.update(seconds) | Call every frame with the time since the last frame. |
avatar.animation | The name of the animation playing, or null. |
avatar.speed | Playback speed, 1 by default. |
avatar.inPlace | true (default): walks and runs stay on the spot and you move the object. false: the hips follow the animation's own motion. |
avatar.stop() | Back to the rest pose. |
avatar.showSkeleton(true) | Draws the skeleton on top, for debugging. |
avatar.dispose() | Removes the avatar and frees its GPU memory. |
await GeneratoAvatar.animations() | The animation list: [{ id, name, category, duration, loop }]. |
What's in your download
| File | What it is |
|---|---|
*.ply | The avatar as a 3D Gaussian splat, about 110,000–150,000 splats and around 5 MB. |
rig.json | The skeleton (22 joints), the avatar's height and the name of its splat file. |
weights.bin | Four bone weights per splat. This is what makes the body bend with the skeleton. |
README.txt | A summary of the files and the licence. |
Good to know
- Versions: use Spark
2.4.0exactly and three.js0.180or newer. - Lighting: the avatar's light is baked in from the photo, so scene lights don't change it. Pick a background that suits it.
- Fog:
scene.foghides splats with Spark 2.4, so leave it off. - Collisions: the avatar has no physics shape. Use a capsule about 0.3 m wide and as tall as the avatar.
- Performance: each avatar is drawn as roughly 110,000–150,000 splats. Start with a few avatars and test on your target devices before adding more.
- Hosting: serve the files from your own site or any CDN. If they're on another domain, that server must send CORS headers.
Game engines and 3D tools (GLB)
When you download, choose FBX for Unity and VRChat, or GLB for Blender, Godot, Unreal, Babylon.js and PlayCanvas. Both are the same avatar; the first export takes about a minute. Each file contains:
- A textured mesh, about 60,000 triangles with a 2048×2048 texture, built from your avatar's own 3D shape and colours.
- A skeleton with Mixamo bone names (
Hips,Spine,LeftArm,LeftUpLeg…), plus a twist bone in each forearm so wrists turn smoothly. - 12 animations: idle, idle-talking, walk, walk-backwards, jog, sprint, strafe-left, strafe-right, greeting, cheering-two-hands, dance-charleston and salute. The file opens standing still in its A-pose (a static first clip named
A-Pose), and each animation is its own clip. - Real-world scale (1.7 m tall), feet on the ground at the origin, facing +Z.
VRChat and Quest (10k triangles)
Choose For VRChat on Quest (FBX, 10k) for the same avatar at 10,000 triangles. That is VRChat's "Good" rank on Quest, so it shows for everyone (Quest hides avatars ranked below Medium by default). It has one material and 24 bones. The texture is painted from the full-detail shape, so up close it looks almost the same as the 60k version.
To upload it: import the free Generato Avatar Tools package into a VRChat avatar project (Creator Companion), drag in the .fbx, click Add to Scene and Set Up for VRChat in the Generato Avatars window that opens (or Tools › Generato › Avatars), then Build & Publish from the VRChat SDK control panel (Windows, Android or both). The tool sets the Humanoid rig, the import settings the SDK checks, a Quest-safe VRChat/Mobile/Toon Lit material and the view position. The full walkthrough is on the VRChat avatar page.
The texture already contains the lighting from the photo, so an unlit or toon shader looks the most like your avatar. Lip sync and blinking aren't set up yet.
| Tool | How to bring it in |
|---|---|
| three.js, Babylon.js, PlayCanvas | Load it with the engine's glTF loader and play the animations by name. |
| Blender | File › Import › glTF 2.0. The animations appear as actions. |
| Godot 4 | Drop the file into your project. Godot imports glTF natively, animations included. |
| Unreal Engine 5 | Import the file (Unreal's glTF importer). You get a skeletal mesh, its skeleton and one animation per clip. |
| Unity | Download the FBX and drop it into your Assets; set the rig to Humanoid to use it with any humanoid animation. (The GLB also works with Unity's glTFast package.) |
The texture has the avatar's lighting baked in, and the material is marked unlit so engines show it as captured. If your engine ignores that, set the material to unlit yourself. Fingers are not rigged separately: each hand moves as one piece.
Splat or mesh? The splat (the web download) is the photo-real version. The mesh is a little softer up close, but it runs anywhere a normal 3D model does.
Platforms
| Platform | Download | |
|---|---|---|
| three.js, React Three Fiber, WebXR | Web (splat) or GLB | The splat with the SDK on this page looks best. The GLB works too. |
| Babylon.js, PlayCanvas | GLB | Standard glTF loader. |
| Unity | FBX | Drag in, set the rig to Humanoid. See Game engines. |
| Unreal, Godot, Blender | GLB or FBX | See Game engines. |
| VRChat (PC and Quest) | FBX (10k for Quest) | Uploaded from Unity with the VRChat SDK. See VRChat and Quest. |
Need another format? Tell us at hello@zoync.com.
Licence
Your avatar: use it in your own personal and commercial projects, such as games, apps, simulations and videos. Don't resell or redistribute the avatar files themselves, and don't use an avatar of a real person without their consent.
The SDK is free to use with your Generato avatars. The animations are CC0. Spark is MIT-licensed.