meshyai

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Meshy AI — 3D Model Generation, Rigging & Animation

Meshy AI — 3D模型生成、骨骼绑定与动画

You are an expert at generating custom 3D models with Meshy AI and integrating them into Three.js browser games. Meshy is the preferred source for all 3D game assets — it generates exactly what you need from a text description or reference image, with consistent art style and game-ready topology.
你是使用Meshy AI生成自定义3D模型并将其集成到Three.js浏览器游戏的专家。Meshy是所有3D游戏资源的首选来源——它可以根据文本描述或参考图片生成完全符合你需求的资源,具备统一的艺术风格和游戏就绪的拓扑结构。

Why Meshy First

为什么优先选择Meshy

  • Exact match: Generate precisely the character, prop, or scenery your game needs — no compromises
  • Consistent style: All assets from the same generation pipeline share a cohesive look
  • Custom characters: Named personalities, branded characters, unique creatures — all generated to spec
  • Full pipeline: Generate → rig → animate, all from one tool
  • Game-ready: Control polycount, topology, and PBR textures for optimal Three.js performance
  • 完全匹配:精准生成游戏所需的角色、道具、场景,无需妥协
  • 风格统一:同一生成管线产出的所有资源都具备协调的视觉效果
  • 自定义角色:有名的个性化角色、品牌角色、独特生物,全部可按规格生成
  • 完整管线:生成→绑定→动画,一个工具即可完成全流程
  • 游戏就绪:可控制面数、拓扑结构、PBR纹理,实现最优的Three.js性能

Fallback Sources

备选来源

If
MESHY_API_KEY
is not available and the user declines to set one up, fall back to these in order:
FallbackSourceBest for
3d-character-library/
Pre-built GLBsQuick animated humanoids (Soldier, Xbot, Robot, Fox)
find-3d-asset.mjs
Sketchfab, Poly Haven, Poly.pizzaSearching existing free model libraries
Procedural geometryCodeBoxGeometry/SphereGeometry as last resort
如果
MESHY_API_KEY
不可用且用户拒绝配置,按以下顺序使用备选来源:
备选方案来源适用场景
3d-character-library/
预构建GLB文件快速获取带动画的人形模型(士兵、Xbot、机器人、狐狸)
find-3d-asset.mjs
Sketchfab、Poly Haven、Poly.pizza搜索现有免费模型库
程序化几何代码万不得已时使用BoxGeometry/SphereGeometry

Authentication

身份验证

All Meshy API calls require
MESHY_API_KEY
. Always check for this key before starting any 3D asset work. If the key is not set in the environment, ask the user immediately:
I'll generate custom 3D models with Meshy AI for the best results. You can get a free API key in 30 seconds:
  1. Sign up at https://app.meshy.ai
  2. Go to Settings → API Keys
  3. Create a new API key
What is your Meshy API key? (Or type "skip" to use free model libraries instead)
If the user provides a key, use it via:
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs ...
If the user skips, proceed with fallback sources (character library → Sketchfab → Poly Haven).
所有Meshy API调用都需要
MESHY_API_KEY
在开始任何3D资源工作前务必检查该密钥。如果环境中未设置该密钥,立即询问用户
我将使用Meshy AI生成自定义3D模型以获得最佳效果。你只需30秒即可获取免费API密钥:
  1. 访问https://app.meshy.ai注册账号
  2. 进入设置→API Keys页面
  3. 创建新的API密钥
你的Meshy API密钥是什么?(或者输入"skip"使用免费模型库替代)
如果用户提供了密钥,通过以下方式使用:
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs ...
如果用户选择跳过,继续使用备选来源(角色库→Sketchfab→Poly Haven)。

CLI Script —
scripts/meshy-generate.mjs

CLI脚本 —
scripts/meshy-generate.mjs

Zero-dependency Node.js script. Handles the full lifecycle: submit task → poll → download GLB → write meta.json.
零依赖的Node.js脚本,处理全生命周期:提交任务→轮询状态→下载GLB→写入meta.json。

Text to 3D (full pipeline)

文本生成3D(全流程)

Generates a 3D model from a text prompt. Two-step process: preview (geometry) → refine (texturing).
bash
undefined
根据文本提示生成3D模型,分为两步:预览(几何结构)→优化(纹理)。
bash
undefined

Full pipeline: preview → refine → download

全流程:预览→优化→下载

MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode text-to-3d
--prompt "a cartoon knight with sword and shield"
--output public/assets/models/
--slug knight
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode text-to-3d
--prompt "a cartoon knight with sword and shield"
--output public/assets/models/
--slug knight

Preview only (faster, untextured — good for geometry check)

仅生成预览(速度更快,无纹理——适合检查几何结构)

MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode text-to-3d
--prompt "a wooden barrel"
--preview-only
--output public/assets/models/
--slug barrel
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode text-to-3d
--prompt "a wooden barrel"
--preview-only
--output public/assets/models/
--slug barrel

With PBR textures and specific polycount

带PBR纹理和指定面数

MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode text-to-3d
--prompt "a sci-fi hover bike"
--pbr
--polycount 15000
--ai-model meshy-6
--output public/assets/models/
--slug hoverbike
undefined
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode text-to-3d
--prompt "a sci-fi hover bike"
--pbr
--polycount 15000
--ai-model meshy-6
--output public/assets/models/
--slug hoverbike
undefined

Image to 3D

图像生成3D

Turn a reference image into a 3D model. Supports URLs, local files, and base64 data URIs.
bash
undefined
将参考图片转换为3D模型,支持URL、本地文件和base64数据URI。
bash
undefined

From URL

从URL生成

MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode image-to-3d
--image "https://example.com/character-concept.png"
--output public/assets/models/
--slug character
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode image-to-3d
--image "https://example.com/character-concept.png"
--output public/assets/models/
--slug character

From local file (auto-converts to base64)

从本地文件生成(自动转换为base64)

MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode image-to-3d
--image "./concept-art/hero.png"
--output public/assets/models/
--slug hero
undefined
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode image-to-3d
--image "./concept-art/hero.png"
--output public/assets/models/
--slug hero
undefined

Auto-Rig (humanoids only — MANDATORY for all bipedal characters)

自动骨骼绑定(仅适用于人形模型——所有双足角色必须执行该步骤)

Adds a skeleton to a generated humanoid model and auto-downloads walking + running animation GLBs. The input task ID comes from a completed text-to-3d or image-to-3d task.
bash
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
  --mode rig \
  --task-id <meshy-task-id> \
  --height 1.8 \
  --output public/assets/models/ \
  --slug hero
This produces 3 files automatically:
  • hero.glb
    — rigged model with skeleton
  • hero-walk.glb
    — walking animation (auto-downloaded)
  • hero-run.glb
    — running animation (auto-downloaded)
Always chain generate → rig as one atomic step for humanoids. Never leave humanoid characters as static models.
Limitations: Rigging works only on textured humanoid (bipedal) models with clearly defined limbs. Won't work on animals, vehicles, abstract shapes, or untextured meshes.
为生成的人形模型添加骨骼,自动下载行走和跑步动画GLB。输入的任务ID来自已完成的文本转3D或图像转3D任务。
bash
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
  --mode rig \
  --task-id <meshy-task-id> \
  --height 1.8 \
  --output public/assets/models/ \
  --slug hero
该操作会自动生成3个文件:
  • hero.glb
    — 带骨骼的绑定后模型
  • hero-walk.glb
    — 行走动画(自动下载)
  • hero-run.glb
    — 跑步动画(自动下载)
人形模型务必将生成→绑定作为一个原子步骤执行,不要让人形角色仅为静态模型。
限制: 骨骼绑定仅适用于带纹理、肢体清晰的人形(双足)模型,不适用于动物、载具、抽象形状或无纹理网格。

Animate

生成动画

Apply an animation to a rigged model. Requires a completed rig task ID and an animation action ID.
bash
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
  --mode animate \
  --task-id <rig-task-id> \
  --action-id 1 \
  --output public/assets/models/ \
  --slug hero-walk
为已绑定骨骼的模型应用动画,需要已完成的绑定任务ID和动画动作ID。
bash
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
  --mode animate \
  --task-id <rig-task-id> \
  --action-id 1 \
  --output public/assets/models/ \
  --slug hero-walk

Check Status

检查状态

Poll any task's current status.
bash
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
  --mode status \
  --task-id <task-id> \
  --task-type text-to-3d   # or: image-to-3d, rigging, animations
轮询任意任务的当前状态。
bash
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
  --mode status \
  --task-id <task-id> \
  --task-type text-to-3d   # 或:image-to-3d, rigging, animations

Non-blocking Mode

非阻塞模式

Submit a task without waiting. Useful in pipelines.
bash
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
  --mode text-to-3d \
  --prompt "a crystal sword" \
  --no-poll
提交任务后无需等待,适合在管线中使用。
bash
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
  --mode text-to-3d \
  --prompt "a crystal sword" \
  --no-poll

Later:

后续查询:

MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode status --task-id <id> --task-type text-to-3d
undefined
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode status --task-id <id> --task-type text-to-3d
undefined

Automatic GLB Optimization

GLB自动优化

All downloaded GLBs are automatically optimized via
scripts/optimize-glb.mjs
to reduce file sizes by 80–95%. The pipeline resizes textures to 1024×1024, converts them to WebP, and applies meshopt compression.
  • Optimization runs by default after every GLB download (text-to-3d, image-to-3d, rig, animate)
  • Use
    --no-optimize
    to skip optimization and keep the raw Meshy output
  • Use
    --texture-size <n>
    to change the max texture dimension (default: 1024)
  • First run may take a moment as
    npx
    downloads
    @gltf-transform/cli
  • If
    gltf-transform
    is unavailable, the script warns and continues with the raw file
Optimized GLBs use meshopt compression and require
MeshoptDecoder
at runtime — the template
AssetLoader.js
includes this automatically.
bash
undefined
所有下载的GLB会通过
scripts/optimize-glb.mjs
自动优化,文件大小可减少80-95%。优化管线会将纹理调整为1024×1024,转换为WebP格式,并应用meshopt压缩。
  • 每次下载GLB后默认执行优化(文本转3D、图像转3D、绑定、动画场景均适用)
  • 使用
    --no-optimize
    可跳过优化,保留Meshy原始输出
  • 使用
    --texture-size <n>
    可更改最大纹理尺寸(默认:1024)
  • 首次运行可能需要一点时间,因为
    npx
    会下载
    @gltf-transform/cli
  • 如果
    gltf-transform
    不可用,脚本会发出警告并继续使用原始文件
优化后的GLB使用meshopt压缩,运行时需要
MeshoptDecoder
——模板的
AssetLoader.js
已自动包含该依赖。
bash
undefined

Skip optimization for a specific generation

某次生成时跳过优化

MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode text-to-3d --prompt "a barrel" --preview-only
--no-optimize --output public/assets/models/ --slug barrel
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode text-to-3d --prompt "a barrel" --preview-only
--no-optimize --output public/assets/models/ --slug barrel

Custom texture size (e.g., 512 for mobile)

自定义纹理尺寸(例如移动端使用512)

MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode text-to-3d --prompt "a barrel" --preview-only
--texture-size 512 --output public/assets/models/ --slug barrel
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode text-to-3d --prompt "a barrel" --preview-only
--texture-size 512 --output public/assets/models/ --slug barrel

Re-optimize an existing GLB directly

直接重新优化现有GLB

node scripts/optimize-glb.mjs public/assets/models/barrel.glb --texture-size 512
undefined
node scripts/optimize-glb.mjs public/assets/models/barrel.glb --texture-size 512
undefined

API Reference

API参考

Base URL:
https://api.meshy.ai/openapi
基础URL:
https://api.meshy.ai/openapi

Text to 3D

文本转3D

POST
/v2/text-to-3d
— Create preview or refine task
Preview payload:
json
{
  "mode": "preview",
  "prompt": "a cartoon knight with sword and shield",
  "ai_model": "latest",
  "topology": "triangle",
  "target_polycount": 10000
}
Refine payload:
json
{
  "mode": "refine",
  "preview_task_id": "<preview-task-id>",
  "enable_pbr": true,
  "texture_prompt": "hand-painted fantasy style"
}
GET
/v2/text-to-3d/:id
— Retrieve task (poll this)
Response when complete:
json
{
  "id": "task-uuid",
  "status": "SUCCEEDED",
  "progress": 100,
  "model_urls": {
    "glb": "https://assets.meshy.ai/...",
    "fbx": "https://assets.meshy.ai/...",
    "obj": "https://assets.meshy.ai/...",
    "usdz": "https://assets.meshy.ai/..."
  },
  "texture_urls": [
    { "base_color": "https://..." }
  ],
  "thumbnail_url": "https://..."
}
Optional parameters:
  • ai_model
    :
    meshy-5
    ,
    meshy-6
    ,
    latest
    (default:
    latest
    )
  • model_type
    :
    standard
    or
    lowpoly
  • topology
    :
    quad
    or
    triangle
    (default:
    triangle
    )
  • target_polycount
    : 100–300,000 (default: 10,000)
  • symmetry_mode
    :
    off
    ,
    auto
    ,
    on
    (default:
    auto
    )
  • pose_mode
    :
    a-pose
    ,
    t-pose
    , or empty string
  • enable_pbr
    : generates metallic, roughness, and normal maps
POST
/v2/text-to-3d
— 创建预览或优化任务
预览请求体:
json
{
  "mode": "preview",
  "prompt": "a cartoon knight with sword and shield",
  "ai_model": "latest",
  "topology": "triangle",
  "target_polycount": 10000
}
优化请求体:
json
{
  "mode": "refine",
  "preview_task_id": "<preview-task-id>",
  "enable_pbr": true,
  "texture_prompt": "hand-painted fantasy style"
}
GET
/v2/text-to-3d/:id
— 获取任务信息(用于轮询)
完成后的响应:
json
{
  "id": "task-uuid",
  "status": "SUCCEEDED",
  "progress": 100,
  "model_urls": {
    "glb": "https://assets.meshy.ai/...",
    "fbx": "https://assets.meshy.ai/...",
    "obj": "https://assets.meshy.ai/...",
    "usdz": "https://assets.meshy.ai/..."
  },
  "texture_urls": [
    { "base_color": "https://..." }
  ],
  "thumbnail_url": "https://..."
}
可选参数:
  • ai_model
    :
    meshy-5
    ,
    meshy-6
    ,
    latest
    (默认:
    latest
  • model_type
    :
    standard
    lowpoly
  • topology
    :
    quad
    triangle
    (默认:
    triangle
  • target_polycount
    : 100–300,000(默认:10,000)
  • symmetry_mode
    :
    off
    ,
    auto
    ,
    on
    (默认:
    auto
  • pose_mode
    :
    a-pose
    ,
    t-pose
    , 或空字符串
  • enable_pbr
    : 生成金属度、粗糙度和法线贴图

Image to 3D

图像转3D

POST
/v1/image-to-3d
— Create task
json
{
  "image_url": "https://example.com/photo.png",
  "ai_model": "latest",
  "enable_pbr": false,
  "should_texture": true,
  "topology": "triangle",
  "target_polycount": 10000
}
GET
/v1/image-to-3d/:id
— Retrieve task
Supports
image_url
as public URL, base64 data URI (
data:image/png;base64,...
), or multi-image via POST
/v1/multi-image-to-3d
(1–4 images from different angles).
POST
/v1/image-to-3d
— 创建任务
json
{
  "image_url": "https://example.com/photo.png",
  "ai_model": "latest",
  "enable_pbr": false,
  "should_texture": true,
  "topology": "triangle",
  "target_polycount": 10000
}
GET
/v1/image-to-3d/:id
— 获取任务信息
支持
image_url
为公共URL、base64数据URI(
data:image/png;base64,...
),或通过POST
/v1/multi-image-to-3d
传入多图(1-4张不同角度的图片)。

Rigging

骨骼绑定

POST
/v1/rigging
— Create rigging task
json
{
  "input_task_id": "<text-to-3d or image-to-3d task id>",
  "height_meters": 1.7
}
GET
/v1/rigging/:id
— Retrieve task
Result includes:
  • rigged_character_glb_url
    — rigged GLB ready for Three.js
  • rigged_character_fbx_url
    — rigged FBX
  • basic_animations
    — walking/running GLB URLs included free
POST
/v1/rigging
— 创建绑定任务
json
{
  "input_task_id": "<text-to-3d 或 image-to-3d 任务ID>",
  "height_meters": 1.7
}
GET
/v1/rigging/:id
— 获取任务信息
结果包含:
  • rigged_character_glb_url
    — 已绑定骨骼、可直接用于Three.js的GLB
  • rigged_character_fbx_url
    — 已绑定骨骼的FBX
  • basic_animations
    — 免费包含的行走/跑步GLB URL

Animation

动画生成

POST
/v1/animations
— Create animation task
json
{
  "rig_task_id": "<rigging-task-id>",
  "action_id": 1
}
GET
/v1/animations/:id
— Retrieve task
Result includes
animation_glb_url
,
animation_fbx_url
.
POST
/v1/animations
— 创建动画任务
json
{
  "rig_task_id": "<绑定任务ID>",
  "action_id": 1
}
GET
/v1/animations/:id
— 获取任务信息
结果包含
animation_glb_url
animation_fbx_url

Task Statuses

任务状态

All tasks progress through:
PENDING
IN_PROGRESS
SUCCEEDED
/
FAILED
/
CANCELED
Poll at 5-second intervals. Tasks typically complete in 30s–5min depending on complexity.
所有任务的状态流转:
PENDING
IN_PROGRESS
SUCCEEDED
/
FAILED
/
CANCELED
每5秒轮询一次,根据复杂度不同,任务通常在30秒到5分钟内完成。

Asset Retention

资源保留

Meshy retains generated assets for 3 days (unlimited for Enterprise). Download promptly.
Meshy会将生成的资源保留3天(企业版无限制),请及时下载。

Quick Reference: Static Props (no rig needed)

快速参考:静态道具(无需绑定)

For non-humanoid assets (props, scenery, buildings), skip rigging:
bash
undefined
对于非人形变体(道具、场景、建筑),可跳过骨骼绑定:
bash
undefined

Generate

生成

MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode text-to-3d --prompt "a wooden barrel, low poly game asset"
--polycount 5000 --output public/assets/models/ --slug barrel
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode text-to-3d --prompt "a wooden barrel, low poly game asset"
--polycount 5000 --output public/assets/models/ --slug barrel

Integrate with loadModel (regular clone, no SkeletonUtils)

用loadModel集成(普通克隆,无需SkeletonUtils)

const barrel = await loadModel('assets/models/barrel.glb'); scene.add(barrel);
undefined
const barrel = await loadModel('assets/models/barrel.glb'); scene.add(barrel);
undefined

Post-Generation Verification (MANDATORY)

生成后验证(必须执行)

After loading any Meshy-generated model, always verify orientation and scale before proceeding. Meshy models have unpredictable facing directions and scales. Skipping this step leads to backwards-facing characters and models that overflow their containers.
加载任何Meshy生成的模型后,务必先验证朝向和缩放再继续后续操作。Meshy模型的朝向和缩放是不可预测的,跳过该步骤会导致角色朝向错误、模型超出容器等问题。

Auto-Orientation Check

自动朝向检查

Meshy models typically face +Z, but this varies. After loading, log the bounding box and visually verify via Playwright MCP or dev tools:
js
// Add this immediately after loading any GLB
model.updateMatrixWorld(true);
const box = new THREE.Box3().setFromObject(model);
const size = box.getSize(new THREE.Vector3());
const center = box.getCenter(new THREE.Vector3());
console.log(`[Model] ${slug} — size: ${size.x.toFixed(2)} x ${size.y.toFixed(2)} x ${size.z.toFixed(2)}`);
console.log(`[Model] ${slug} — center: ${center.x.toFixed(2)}, ${center.y.toFixed(2)}, ${center.z.toFixed(2)}`);
Fixing facing direction:
  • Start with
    rotationY: Math.PI
    (180 degrees) — most Meshy models need this to face -Z
  • If the model faces +Z by default and needs to face the camera:
    rotationY: 0
  • If in doubt: take a screenshot, check which way the face/front is pointing, adjust
  • Store
    rotationY
    in Constants.js per model — never hardcode in entity files
Meshy模型通常朝向+Z方向,但也存在差异。加载后,打印包围盒信息并通过Playwright MCP或开发者工具进行视觉验证
js
// 加载任意GLB后立即添加该代码
model.updateMatrixWorld(true);
const box = new THREE.Box3().setFromObject(model);
const size = box.getSize(new THREE.Vector3());
const center = box.getCenter(new THREE.Vector3());
console.log(`[Model] ${slug} — 尺寸: ${size.x.toFixed(2)} x ${size.y.toFixed(2)} x ${size.z.toFixed(2)}`);
console.log(`[Model] ${slug} — 中心: ${center.x.toFixed(2)}, ${center.y.toFixed(2)}, ${center.z.toFixed(2)}`);
修复朝向:
  • 首先尝试
    rotationY: Math.PI
    (180度旋转)——大多数Meshy模型需要该配置来朝向-Z
  • 如果模型默认朝向+Z且需要朝向相机:设置
    rotationY: 0
  • 存在疑问时:截图查看面部/正面朝向,再进行调整
  • rotationY
    按模型存入Constants.js——不要在实体文件中硬编码

Auto-Scale Fitting

自动缩放适配

Models must fit within their game context. After loading:
js
// Calculate scale to fit a target height
const box = new THREE.Box3().setFromObject(model);
const currentHeight = box.max.y - box.min.y;
const targetHeight = 2.0; // desired height in world units
const autoScale = targetHeight / currentHeight;
model.scale.setScalar(autoScale);
For container fitting (e.g., robots inside a ring):
js
// Ensure model fits within container bounds
const containerWidth = RING.PLATFORM_WIDTH * 0.8; // 80% of ring width
const modelWidth = box.max.x - box.min.x;
if (modelWidth * currentScale > containerWidth) {
  const fitScale = containerWidth / modelWidth;
  model.scale.setScalar(Math.min(currentScale, fitScale));
}
Always take a Playwright screenshot after model integration to visually verify:
  1. Characters face the correct direction
  2. Characters fit within their environment
  3. Characters don't clip through floors/walls/each other
模型必须适配游戏场景的上下文,加载后执行:
js
// 计算缩放比例以匹配目标高度
const box = new THREE.Box3().setFromObject(model);
const currentHeight = box.max.y - box.min.y;
const targetHeight = 2.0; // 期望的世界单位高度
const autoScale = targetHeight / currentHeight;
model.scale.setScalar(autoScale);
容器适配(例如机器人放在擂台内):
js
// 确保模型适配容器边界
const containerWidth = RING.PLATFORM_WIDTH * 0.8; // 擂台宽度的80%
const modelWidth = box.max.x - box.min.x;
if (modelWidth * currentScale > containerWidth) {
  const fitScale = containerWidth / modelWidth;
  model.scale.setScalar(Math.min(currentScale, fitScale));
}
模型集成后务必通过Playwright截图进行视觉验证:
  1. 角色朝向正确
  2. 角色适配环境大小
  3. 角色不会穿模到地板/墙壁/其他模型中

Floor Alignment

地板对齐

Center the model on X/Z and plant feet on Y=0:
js
const box = new THREE.Box3().setFromObject(model);
const center = box.getCenter(new THREE.Vector3());
model.position.y = -box.min.y;      // feet on ground
model.position.x = -center.x;       // centered X
model.position.z = -center.z;       // centered Z
将模型在X/Z轴居中,脚部落到Y=0平面:
js
const box = new THREE.Box3().setFromObject(model);
const center = box.getCenter(new THREE.Vector3());
model.position.y = -box.min.y;      // 脚接触地面
model.position.x = -center.x;       // X轴居中
model.position.z = -center.z;       // Z轴居中

Rigging: Mandatory for Humanoid Characters

骨骼绑定:人形角色必须执行

Every humanoid character MUST be rigged. Static models require hacky programmatic animation (moving wrapper groups) that looks artificial. Rigged models get proper skeletal animation — walk, run, punch, etc.
所有人形角色必须进行骨骼绑定。静态模型需要使用hacky的编程式动画(移动包装组),视觉效果很假。绑定后的模型可以实现自然的骨骼动画:行走、跑步、拳击等。

When to Rig

何时需要绑定

Model typeRig?Why
Humanoid character (player, NPC, enemy)YES — alwaysSkeletal animation for walk/run/idle/attack
Animal with legsYESWalk/run animations
Vehicle, prop, buildingNoStatic or simple rotation
Abstract shape, particleNoProcedural animation
模型类型是否需要绑定原因
人形角色(玩家、NPC、敌人)是,必须可实现行走/跑步/ idle/攻击等骨骼动画
有腿的动物可实现行走/跑步动画
载具、道具、建筑静态或简单旋转即可
抽象形状、粒子使用程序化动画即可

Full Pipeline: Generate → Rig → Animate → Integrate

全流程:生成→绑定→动画→集成

Step 1: Generate the model
bash
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
  --mode text-to-3d \
  --prompt "a stylized robot boxer, low poly game character, full body" \
  --pbr --polycount 15000 \
  --output public/assets/models/ --slug robot
Step 2: Rig (reads refineTaskId from meta.json automatically)
bash
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
  --mode rig \
  --task-id <refine-task-id-from-meta.json> \
  --height 1.7 \
  --output public/assets/models/ --slug robot-rigged
Rigging returns:
  • rigged_character_glb_url
    — rigged GLB with skeleton (use this as the base model)
  • basic_animations.walking
    — walking animation GLB (free, included)
  • basic_animations.running
    — running animation GLB (free, included)
Step 3: Add custom animations (optional, for game-specific actions)
bash
undefined
步骤1:生成模型
bash
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
  --mode text-to-3d \
  --prompt "a stylized robot boxer, low poly game character, full body" \
  --pbr --polycount 15000 \
  --output public/assets/models/ --slug robot
步骤2:骨骼绑定(自动从meta.json读取refineTaskId)
bash
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
  --mode rig \
  --task-id <refine-task-id-from-meta.json> \
  --height 1.7 \
  --output public/assets/models/ --slug robot-rigged
绑定结果返回:
  • rigged_character_glb_url
    — 带骨骼的绑定GLB(作为基础模型使用)
  • basic_animations.walking
    — 行走动画GLB(免费包含)
  • basic_animations.running
    — 跑步动画GLB(免费包含)
步骤3:添加自定义动画(可选,用于游戏专属动作)
bash
undefined

Each action_id corresponds to a different animation

每个action_id对应不同的动画

MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode animate
--task-id <rig-task-id>
--action-id <id>
--output public/assets/models/ --slug robot-punch

**Step 4: Integrate** with `loadAnimatedModel()` + `AnimationMixer`:
```js
import { loadAnimatedModel } from './level/AssetLoader.js';
import * as THREE from 'three';

// Load rigged model (SkeletonUtils.clone preserves bone bindings)
const { model, clips } = await loadAnimatedModel('assets/models/robot-rigged.glb');
const mixer = new THREE.AnimationMixer(model);

// Log clip names — they vary per model
console.log('Clips:', clips.map(c => c.name));

// Load additional animation GLBs and add their clips to the same mixer
const walkData = await loadAnimatedModel('assets/models/robot-walk.glb');
const walkClip = walkData.clips[0];
const walkAction = mixer.clipAction(walkClip);

// fadeToAction pattern for smooth transitions
function fadeToAction(nextAction, duration = 0.3) {
  if (activeAction) activeAction.fadeOut(duration);
  nextAction.reset().setEffectiveTimeScale(1).setEffectiveWeight(1).fadeIn(duration).play();
  activeAction = nextAction;
}

// In update loop:
mixer.update(delta);
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode animate
--task-id <rig-task-id>
--action-id <id>
--output public/assets/models/ --slug robot-punch

**步骤4:集成**,使用`loadAnimatedModel()` + `AnimationMixer`:
```js
import { loadAnimatedModel } from './level/AssetLoader.js';
import * as THREE from 'three';

// 加载绑定后的模型(SkeletonUtils.clone会保留骨骼绑定关系)
const { model, clips } = await loadAnimatedModel('assets/models/robot-rigged.glb');
const mixer = new THREE.AnimationMixer(model);

// 打印clip名称——不同模型的名称不同
console.log('Clips:', clips.map(c => c.name));

// 加载额外的动画GLB,将其clip添加到同一个mixer中
const walkData = await loadAnimatedModel('assets/models/robot-walk.glb');
const walkClip = walkData.clips[0];
const walkAction = mixer.clipAction(walkClip);

// fadeToAction模式实现平滑过渡
function fadeToAction(nextAction, duration = 0.3) {
  if (activeAction) activeAction.fadeOut(duration);
  nextAction.reset().setEffectiveTimeScale(1).setEffectiveWeight(1).fadeIn(duration).play();
  activeAction = nextAction;
}

// 更新循环中调用:
mixer.update(delta);

Prompt Engineering Tips

提示词工程技巧

Good prompts produce better models:
GoalPromptWhy
Game character"a stylized goblin warrior, low poly game character, full body""low poly" + "game character" = game-ready topology
Prop"a wooden treasure chest, stylized, closed"Simple, specific, single object
Environment piece"a fantasy stone archway, low poly, game asset""game asset" signals clean geometry
Vehicle"a sci-fi hover bike, side view, clean topology""clean topology" = fewer artifacts
Avoid:
  • Multiple objects in one prompt ("a knight AND a dragon") — generate separately
  • Vague prompts ("something cool") — be specific about style and form
  • Interior/architectural scenes — Meshy is best for single objects
优质的提示词可以生成更好的模型:
目标提示词原因
游戏角色"a stylized goblin warrior, low poly game character, full body""low poly" + "game character" = 游戏就绪的拓扑结构
道具"a wooden treasure chest, stylized, closed"简单、具体、单一对象
环境组件"a fantasy stone archway, low poly, game asset""game asset"代表需要干净的几何结构
载具"a sci-fi hover bike, side view, clean topology""clean topology" = 更少的瑕疵
避免:
  • 单个提示词包含多个对象("a knight AND a dragon")——分开生成
  • 模糊的提示词("something cool")——明确指定风格和形态
  • 室内/建筑场景——Meshy最适合生成单一对象

Integration with Existing Pipeline

与现有管线集成

Meshy-generated models slot into the existing 3D asset pipeline:
┌─────────────────────────────────────────────────────┐
│                 3D Asset Sources                     │
├──────────────┬──────────────┬───────────────────────┤
│ Free Libraries│ Character Lib │     Meshy AI          │
│ find-3d-asset │ 3d-char-lib/ │ meshy-generate.mjs    │
│   .mjs       │              │ text/image → 3D       │
│              │              │ rig → animate         │
├──────────────┴──────────────┴───────────────────────┤
│              AssetLoader.js                         │
│         loadModel() / loadAnimatedModel()           │
├─────────────────────────────────────────────────────┤
│              Three.js Game                          │
└─────────────────────────────────────────────────────┘
All sources output GLB files into
public/assets/models/
. The
AssetLoader.js
doesn't care where the GLB came from — it loads them all the same way.
Meshy生成的模型可直接接入现有3D资源管线:
┌─────────────────────────────────────────────────────┐
│                 3D资源来源                     │
├──────────────┬──────────────┬───────────────────────┤
│ 免费库│ 角色库 │     Meshy AI          │
│ find-3d-asset │ 3d-char-lib/ │ meshy-generate.mjs    │
│   .mjs       │              │ 文本/图像转3D       │
│              │              │ 绑定→动画         │
├──────────────┴──────────────┴───────────────────────┤
│              AssetLoader.js                         │
│         loadModel() / loadAnimatedModel()           │
├─────────────────────────────────────────────────────┤
│              Three.js 游戏                          │
└─────────────────────────────────────────────────────┘
所有来源都输出GLB文件到
public/assets/models/
目录,
AssetLoader.js
不关心GLB的来源,统一按相同方式加载。

Checklist

检查清单

  • MESHY_API_KEY
    checked — prompted user if not set, or user skipped to fallbacks
  • Prompt is specific (style, poly count, single object)
  • All humanoid characters rigged — never skip rigging for bipedal models
  • Downloaded GLB before 3-day expiration
  • Post-generation verification done — orientation, scale, floor alignment checked
  • Playwright screenshot taken — visually confirmed facing direction + fit in environment
  • rotationY
    set per model in Constants.js (most Meshy models need
    Math.PI
    )
  • Static models use
    loadModel()
    (regular clone)
  • Rigged models use
    loadAnimatedModel()
    (SkeletonUtils.clone)
  • Clip names logged and
    clipMap
    defined for animated models
  • .meta.json
    saved alongside GLB with task IDs for traceability
  • npm run build
    succeeds
  • 已检查
    MESHY_API_KEY
    ——未设置时已提示用户,或用户选择跳过使用备选来源
  • 提示词具体(包含风格、面数、单一对象)
  • 所有人形角色已完成骨骼绑定——双足模型绝对不能跳过绑定
  • 已在3天过期前下载GLB
  • 已完成生成后验证——朝向、缩放、地板对齐均已检查
  • 已拍摄Playwright截图——视觉确认朝向正确、适配环境
  • 已在Constants.js中按模型设置
    rotationY
    (大多数Meshy模型需要
    Math.PI
  • 静态模型使用
    loadModel()
    (普通克隆)
  • 绑定后的模型使用
    loadAnimatedModel()
    (SkeletonUtils.clone)
  • 已打印clip名称,且已为动画模型定义
    clipMap
  • .meta.json
    已和GLB保存在同目录,包含任务ID可追溯
  • npm run build
    执行成功