meshyai
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMeshy 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 is not available and the user declines to set one up, fall back to these in order:
MESHY_API_KEY| Fallback | Source | Best for |
|---|---|---|
| Pre-built GLBs | Quick animated humanoids (Soldier, Xbot, Robot, Fox) |
| Sketchfab, Poly Haven, Poly.pizza | Searching existing free model libraries |
| Procedural geometry | Code | BoxGeometry/SphereGeometry as last resort |
如果不可用且用户拒绝配置,按以下顺序使用备选来源:
MESHY_API_KEY| 备选方案 | 来源 | 适用场景 |
|---|---|---|
| 预构建GLB文件 | 快速获取带动画的人形模型(士兵、Xbot、机器人、狐狸) |
| Sketchfab、Poly Haven、Poly.pizza | 搜索现有免费模型库 |
| 程序化几何 | 代码 | 万不得已时使用BoxGeometry/SphereGeometry |
Authentication
身份验证
All Meshy API calls require . Always check for this key before starting any 3D asset work. If the key is not set in the environment, ask the user immediately:
MESHY_API_KEYI'll generate custom 3D models with Meshy AI for the best results. You can get a free API key in 30 seconds:
- Sign up at https://app.meshy.ai
- Go to Settings → API Keys
- 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调用都需要。在开始任何3D资源工作前务必检查该密钥。如果环境中未设置该密钥,立即询问用户:
MESHY_API_KEY我将使用Meshy AI生成自定义3D模型以获得最佳效果。你只需30秒即可获取免费API密钥:
- 访问https://app.meshy.ai注册账号
- 进入设置→API Keys页面
- 创建新的API密钥
你的Meshy API密钥是什么?(或者输入"skip"使用免费模型库替代)
如果用户提供了密钥,通过以下方式使用:
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs ...如果用户选择跳过,继续使用备选来源(角色库→Sketchfab→Poly Haven)。
CLI Script — scripts/meshy-generate.mjs
scripts/meshy-generate.mjsCLI脚本 — scripts/meshy-generate.mjs
scripts/meshy-generate.mjsZero-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
undefinedFull 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
--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
--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
--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
--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
--mode text-to-3d
--prompt "a sci-fi hover bike"
--pbr
--polycount 15000
--ai-model meshy-6
--output public/assets/models/
--slug hoverbike
undefinedMESHY_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
--mode text-to-3d
--prompt "a sci-fi hover bike"
--pbr
--polycount 15000
--ai-model meshy-6
--output public/assets/models/
--slug hoverbike
undefinedImage 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
undefinedFrom 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
--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
--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
--mode image-to-3d
--image "./concept-art/hero.png"
--output public/assets/models/
--slug hero
undefinedMESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode image-to-3d
--image "./concept-art/hero.png"
--output public/assets/models/
--slug hero
--mode image-to-3d
--image "./concept-art/hero.png"
--output public/assets/models/
--slug hero
undefinedAuto-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 heroThis produces 3 files automatically:
- — rigged model with skeleton
hero.glb - — walking animation (auto-downloaded)
hero-walk.glb - — running animation (auto-downloaded)
hero-run.glb
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-walkCheck 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, animationsNon-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-pollLater:
后续查询:
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode status --task-id <id> --task-type text-to-3d
--mode status --task-id <id> --task-type text-to-3d
undefinedMESHY_API_KEY=<key> node scripts/meshy-generate.mjs
--mode status --task-id <id> --task-type text-to-3d
--mode status --task-id <id> --task-type text-to-3d
undefinedAutomatic GLB Optimization
GLB自动优化
All downloaded GLBs are automatically optimized via to reduce file sizes by 80–95%. The pipeline resizes textures to 1024×1024, converts them to WebP, and applies meshopt compression.
scripts/optimize-glb.mjs- Optimization runs by default after every GLB download (text-to-3d, image-to-3d, rig, animate)
- Use to skip optimization and keep the raw Meshy output
--no-optimize - Use to change the max texture dimension (default: 1024)
--texture-size <n> - First run may take a moment as downloads
npx@gltf-transform/cli - If is unavailable, the script warns and continues with the raw file
gltf-transform
Optimized GLBs use meshopt compression and require at runtime — the template includes this automatically.
MeshoptDecoderAssetLoader.jsbash
undefined所有下载的GLB会通过自动优化,文件大小可减少80-95%。优化管线会将纹理调整为1024×1024,转换为WebP格式,并应用meshopt压缩。
scripts/optimize-glb.mjs- 每次下载GLB后默认执行优化(文本转3D、图像转3D、绑定、动画场景均适用)
- 使用可跳过优化,保留Meshy原始输出
--no-optimize - 使用可更改最大纹理尺寸(默认:1024)
--texture-size <n> - 首次运行可能需要一点时间,因为会下载
npx@gltf-transform/cli - 如果不可用,脚本会发出警告并继续使用原始文件
gltf-transform
优化后的GLB使用meshopt压缩,运行时需要——模板的已自动包含该依赖。
MeshoptDecoderAssetLoader.jsbash
undefinedSkip 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
--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
--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
--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
--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
undefinednode scripts/optimize-glb.mjs public/assets/models/barrel.glb --texture-size 512
undefinedAPI Reference
API参考
Base URL:
https://api.meshy.ai/openapi基础URL:
https://api.meshy.ai/openapiText to 3D
文本转3D
POST — Create preview or refine task
/v2/text-to-3dPreview 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 — Retrieve task (poll this)
/v2/text-to-3d/:idResponse 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(default:latest)latest - :
model_typeorstandardlowpoly - :
topologyorquad(default:triangle)triangle - : 100–300,000 (default: 10,000)
target_polycount - :
symmetry_mode,off,auto(default:on)auto - :
pose_mode,a-pose, or empty stringt-pose - : generates metallic, roughness, and normal maps
enable_pbr
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或standardlowpoly - :
topology或quad(默认:triangle)triangle - : 100–300,000(默认:10,000)
target_polycount - :
symmetry_mode,off,auto(默认:on)auto - :
pose_mode,a-pose, 或空字符串t-pose - : 生成金属度、粗糙度和法线贴图
enable_pbr
Image to 3D
图像转3D
POST — Create task
/v1/image-to-3djson
{
"image_url": "https://example.com/photo.png",
"ai_model": "latest",
"enable_pbr": false,
"should_texture": true,
"topology": "triangle",
"target_polycount": 10000
}GET — Retrieve task
/v1/image-to-3d/:idSupports as public URL, base64 data URI (), or multi-image via POST (1–4 images from different angles).
image_urldata:image/png;base64,.../v1/multi-image-to-3dPOST — 创建任务
/v1/image-to-3djson
{
"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支持为公共URL、base64数据URI(),或通过POST 传入多图(1-4张不同角度的图片)。
image_urldata:image/png;base64,.../v1/multi-image-to-3dRigging
骨骼绑定
POST — Create rigging task
/v1/riggingjson
{
"input_task_id": "<text-to-3d or image-to-3d task id>",
"height_meters": 1.7
}GET — Retrieve task
/v1/rigging/:idResult includes:
- — rigged GLB ready for Three.js
rigged_character_glb_url - — rigged FBX
rigged_character_fbx_url - — walking/running GLB URLs included free
basic_animations
POST — 创建绑定任务
/v1/riggingjson
{
"input_task_id": "<text-to-3d 或 image-to-3d 任务ID>",
"height_meters": 1.7
}GET — 获取任务信息
/v1/rigging/:id结果包含:
- — 已绑定骨骼、可直接用于Three.js的GLB
rigged_character_glb_url - — 已绑定骨骼的FBX
rigged_character_fbx_url - — 免费包含的行走/跑步GLB URL
basic_animations
Animation
动画生成
POST — Create animation task
/v1/animationsjson
{
"rig_task_id": "<rigging-task-id>",
"action_id": 1
}GET — Retrieve task
/v1/animations/:idResult includes , .
animation_glb_urlanimation_fbx_urlPOST — 创建动画任务
/v1/animationsjson
{
"rig_task_id": "<绑定任务ID>",
"action_id": 1
}GET — 获取任务信息
/v1/animations/:id结果包含、。
animation_glb_urlanimation_fbx_urlTask Statuses
任务状态
All tasks progress through: → → / /
PENDINGIN_PROGRESSSUCCEEDEDFAILEDCANCELEDPoll at 5-second intervals. Tasks typically complete in 30s–5min depending on complexity.
所有任务的状态流转: → → / /
PENDINGIN_PROGRESSSUCCEEDEDFAILEDCANCELED每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
undefinedGenerate
生成
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
--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
--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);
undefinedconst barrel = await loadModel('assets/models/barrel.glb');
scene.add(barrel);
undefinedPost-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 (180 degrees) — most Meshy models need this to face -Z
rotationY: Math.PI - 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 in Constants.js per model — never hardcode in entity files
rotationY
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)}`);修复朝向:
- 首先尝试(180度旋转)——大多数Meshy模型需要该配置来朝向-Z
rotationY: Math.PI - 如果模型默认朝向+Z且需要朝向相机:设置
rotationY: 0 - 存在疑问时:截图查看面部/正面朝向,再进行调整
- 将按模型存入Constants.js——不要在实体文件中硬编码
rotationY
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:
- Characters face the correct direction
- Characters fit within their environment
- 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截图进行视觉验证:
- 角色朝向正确
- 角色适配环境大小
- 角色不会穿模到地板/墙壁/其他模型中
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 type | Rig? | Why |
|---|---|---|
| Humanoid character (player, NPC, enemy) | YES — always | Skeletal animation for walk/run/idle/attack |
| Animal with legs | YES | Walk/run animations |
| Vehicle, prop, building | No | Static or simple rotation |
| Abstract shape, particle | No | Procedural 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 robotStep 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-riggedRigging returns:
- — rigged GLB with skeleton (use this as the base model)
rigged_character_glb_url - — walking animation GLB (free, included)
basic_animations.walking - — running animation GLB (free, included)
basic_animations.running
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绑定结果返回:
- — 带骨骼的绑定GLB(作为基础模型使用)
rigged_character_glb_url - — 行走动画GLB(免费包含)
basic_animations.walking - — 跑步动画GLB(免费包含)
basic_animations.running
步骤3:添加自定义动画(可选,用于游戏专属动作)
bash
undefinedEach 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
--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
--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:
| Goal | Prompt | Why |
|---|---|---|
| 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 . The doesn't care where the GLB came from — it loads them all the same way.
public/assets/models/AssetLoader.jsMeshy生成的模型可直接接入现有3D资源管线:
┌─────────────────────────────────────────────────────┐
│ 3D资源来源 │
├──────────────┬──────────────┬───────────────────────┤
│ 免费库│ 角色库 │ Meshy AI │
│ find-3d-asset │ 3d-char-lib/ │ meshy-generate.mjs │
│ .mjs │ │ 文本/图像转3D │
│ │ │ 绑定→动画 │
├──────────────┴──────────────┴───────────────────────┤
│ AssetLoader.js │
│ loadModel() / loadAnimatedModel() │
├─────────────────────────────────────────────────────┤
│ Three.js 游戏 │
└─────────────────────────────────────────────────────┘所有来源都输出GLB文件到目录,不关心GLB的来源,统一按相同方式加载。
public/assets/models/AssetLoader.jsChecklist
检查清单
- checked — prompted user if not set, or user skipped to fallbacks
MESHY_API_KEY - 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
- set per model in Constants.js (most Meshy models need
rotationY)Math.PI - Static models use (regular clone)
loadModel() - Rigged models use (SkeletonUtils.clone)
loadAnimatedModel() - Clip names logged and defined for animated models
clipMap - saved alongside GLB with task IDs for traceability
.meta.json - succeeds
npm run build
- 已检查——未设置时已提示用户,或用户选择跳过使用备选来源
MESHY_API_KEY - 提示词具体(包含风格、面数、单一对象)
- 所有人形角色已完成骨骼绑定——双足模型绝对不能跳过绑定
- 已在3天过期前下载GLB
- 已完成生成后验证——朝向、缩放、地板对齐均已检查
- 已拍摄Playwright截图——视觉确认朝向正确、适配环境
- 已在Constants.js中按模型设置(大多数Meshy模型需要
rotationY)Math.PI - 静态模型使用(普通克隆)
loadModel() - 绑定后的模型使用(SkeletonUtils.clone)
loadAnimatedModel() - 已打印clip名称,且已为动画模型定义
clipMap - 已和GLB保存在同目录,包含任务ID可追溯
.meta.json - 执行成功
npm run build