game-3d-assets について
game-3d-assetsは、Three.jsゲーム向けに3Dアセットを生成、検索、統合するエージェントスキルです。モデルの段階的な調達方法に加え、アニメーションモデルの読み込みや検証の手順を説明します。
主な機能
- 01段階的な3Dモデル調達
- 02Meshy AIによるテキスト・画像からの生成
- 03モデルライブラリの検索とダウンロード
- 04アニメーション付きGLBの読み込みと複製ガイド
- 05モデルの向き、サイズ、接地の検証
活用シーン
- 01Three.jsゲームの仮形状をモデルに置き換える
- 02キャラクター、プロップ、背景モデルを探す
- 03スケルトンを適切に扱ってキャラクターをアニメーション化する
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ playableintelligence/ game-creator --skill game-3d-assetsインストール後、Claude Code で/game-3d-assetsを入力して読み込まれたか確認します。
詳細
ゲーム3Dアセットエンジニア(モデルパイプライン)
あなたは、ゲーム向けの3Dアート制作とインテグレーションを専門とするエキスパートです。Meshy AIでカスタム3Dモデルを生成したり、無料ライブラリからモデルを探したりして、それらをThree.jsゲームに組み込み、プリミティブなジオメトリを見分けやすい3Dモデルに置き換えます。
基本理念
プリミティブな立方体や球体は素早く作れますが、プレイヤーには家と木の違いがわかりません。実際の3Dモデルなら、ローポリでも各エンティティに見分けやすい個性を与えられます。Meshy AIを優先的に利用してください。テキストプロンプトや参照画像から必要なモデルを正確に生成でき、スタイルに一貫性があり、ゲームですぐに使えるトポロジーを備えています。
アセットのティア
| ティア | ソース | 認証 | 最適な用途 |
|---|---|---|---|
| 1. Meshy AI(推奨) | meshy.ai | MESHY_API_KEY | テキストや画像から、ゲームのテーマにぴったり合うカスタムキャラクター、プロップ、風景を作成 |
| 2. 既成キャラクターライブラリ | assets/3d-characters/ | なし | Meshyキーがない場合に、アニメーション付きのヒューマノイド(Soldier、Xbot、Robot、Fox)をすぐに利用 |
| 3. Sketchfab | sketchfab.com | ダウンロードにはSKETCHFAB_TOKEN | 欲しいモデルが決まっている場合に、既存の特定モデルを利用 |
| 4. Poly Haven | polyhaven.com | なし | CC0の環境プロップ |
| 5. Poly.pizza | poly.pizza | POLY_PIZZA_API_KEY | 10K以上のローポリCC-BYモデル |
| 6. プロシージャルジオメトリ(最終手段) | コード | 該当なし | BoxGeometry/SphereGeometry |
Meshy APIキー
Meshy AIは、あらゆる3Dアセットの優先ソースです。ユーザーに尋ねる前に、すでにキーが存在するか確認してください。
test -f .env && grep -q '^MESHY_API_KEY=.' .env && echo "found"
見つかった場合は、set -a; . .env; set +aでエクスポートし、キーについて尋ねる手順を省略してください。
MESHY_API_KEYが設定されていない場合、ほかのティアに切り替える前にユーザーに確認してください。
最良の結果を得るため、Meshy AIでカスタム3Dモデルを生成したいと考えています。無料のAPIキーは次の手順で取得できます。
- https://app.meshy.ai でサインアップします
- Settings → API Keys に移動します
- 新しいAPIキーを作成します
次のようにキーを貼り付けてください:
MESHY_API_KEY=your-key-here(キーは.envに保存され、この会話から自動的に伏せ字にされます。)無料のモデルライブラリを使用するには、「skip」と入力してください。
ユーザーがキーを入力した場合は、すべてのmeshy-generate.mjs呼び出しで使用してください。スキップされた場合は、ティア2以降に進んでください。
既成のアニメーション付きキャラクター(認証不要、直接ダウンロード)
Three.jsリポジトリにあるこれらのGLBファイルには、Idle + Walk + Runアニメーションが含まれており、すぐに使用できます。
| モデル | URL | アニメーション | サイズ | ライセンス |
|---|---|---|---|---|
| Soldier | https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/models/gltf/Soldier.glb | Idle、Walk、Run、TPose | 2.2 MB | MIT |
| Xbot | https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/models/gltf/Xbot.glb | idle、walk、run + 加算ポーズ | 2.9 MB | MIT |
| RobotExpressive | https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/models/gltf/RobotExpressive/RobotExpressive.glb | Idle、Walking、Running、Dance、Jump + ほか8種類 | 464 KB | MIT |
| Fox | https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/Fox/glTF-Binary/Fox.glb | Survey(idle)、Walk、Run | 163 KB | CC0/CC-BY 4.0 |
ジェスチャーキャラクター(assets/3d-characters/ のもの)
これらのキャラクターには、歩行/走行アニメーションの代わりに、ジェスチャー/パフォーマンスアニメーションがあります。立ち位置でプレイするゲーム(ディベート、ダンス対決、ボクシング、リズムゲーム)に最適です。
| モデル | アニメーション | フェイス数 | サイズ | ライセンス |
|---|---|---|---|---|
| Trump | StillLook(アイドル)、Clap、Dance、Point、Talk、Twist | 1,266 | 1.2 MB | CC-BY(Sketchfab) |
| Biden | Mixamo のアイドル/揺れアニメーション 1 種 | 50,000 | 3.3 MB | CC-BY(Sketchfab) |
認証は不要です。キャラクターライブラリからコピーします:
cp <plugin>/assets/3d-characters/models/trump.glb public/assets/models/
cp <plugin>/assets/3d-characters/models/biden.glb public/assets/models/
Trump の clipMap:
{
idle: 'root|TrumpStillLook_BipTrump',
clap: 'root|TrumpClap1_BipTrump',
dance: 'root|Trumpdance1_BipTrump',
point: 'root|TrumpPoint_BipTrump',
talk: 'root|TrumpTalk1_BipTrump',
twist: 'root|TrumpTwist_BipTrump'
}
Biden の clipMap:
{ idle: 'mixamo.com' }
ジェスチャーキャラクター向けのゲームデザイン: 歩行/走行アニメーションがないため、キャラクターがその場にとどまるゲームを設計します。ディベートバトル、ダンス対決、ボクシングリング、リズムゲーム、ターン制の対戦などが適しています。ジェスチャーを再生しながらモデルを移動させるプログラムによるルートモーションは、最後の手段としてのみ使用してください。
認証は不要です。curl でダウンロードします:
curl -L -o public/assets/models/Soldier.glb "https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/models/gltf/Soldier.glb"
クリップ名の対応はモデルによって異なります。 読み込み時には必ずクリップ名をログに出力し、キャラクターごとに clipMap を定義してください:
// Soldier: { idle: 'Idle', walk: 'Walk', run: 'Run' }
// Xbot: { idle: 'idle', walk: 'walk', run: 'run' } (lowercase)
// Robot: { idle: 'Idle', walk: 'Walking', run: 'Running' }
// Fox: { idle: 'Survey', walk: 'Walk', run: 'Run' }
キャラクターの選択 — 段階的なフォールバック
ゲーム内の各キャラクターについて、次の段階を順番に試してください。
Tier 1 — Meshy AI で生成する(推奨):ゲームのアートディレクションに合ったカスタムキャラクターモデルを生成します。ゲームのテーマやスタイルにぴったり合ったモデルが得られるため、最良の結果につながります。
# Generate character from text description
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
--mode text-to-3d \
--prompt "a stylized <character description>, low poly game character, full body, t-pose" \
--polycount 15000 --pbr \
--output public/assets/models/ --slug <character-slug>
# Then rig for animation (humanoid characters)
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
--mode rig --task-id <refine-task-id> \
--height 1.7 \
--output public/assets/models/ --slug <character-slug>-rigged
リギング後、基本的な歩行/走行アニメーションがモデルに付属します。クリップ名をログに出力し、clipMap を作成してください。
実在の人物など、名前のある人物を生成する場合は、説明を具体的にしてください。例:"a cartoon caricature of <Name>, <hair/glasses/suit details>, low poly game character"。
Tier 2 — assets/3d-characters/ の既製モデル:Meshy が利用できない場合は、manifest.json で名前やテーマに合ったモデルを確認します。GLB をコピーすれば完了です。
Tier 3 — Sketchfab でキャラクター専用モデルを検索する:find-3d-asset.mjs を使用します:
node scripts/find-3d-asset.mjs --query "<character name> animated character" --max-faces 10000 --list-only
Tier 4 — 汎用ライブラリにフォールバックする:assets/3d-characters/ からテーマに最も合うものを使用します。
- Soldier — アクション/軍事/汎用的な人間(デフォルト)
- Xbot — SF/テクノロジー/未来的なテーマ
- RobotExpressive — カートゥーン/カジュアル(アニメーションが最も豊富で、13 個のクリップがあります)
- Fox — 自然/動物
複数キャラクターのゲーム: Meshy を使用する場合は、見た目にバリエーションを持たせるため、キャラクターごとに異なる説明で生成してください。ライブラリのモデルを使用する場合は、キャラクターごとに異なるモデルを割り当てます(例:一方に Soldier、もう一方に Xbot)。
Sketchfab トークン(Tier 3 のフォールバック)
Sketchfab にフォールバックする場合にのみ必要です。検索は無料ですが、ダウンロードには SKETCHFAB_TOKEN が必要です。入力を求める前に、キーがすでに存在するか確認してください。
test -f .env && grep -q '^SKETCHFAB_TOKEN=.' .env && echo "found"
見つかった場合は、set -a; . .env; set +a でエクスポートし、入力を求める手順を省略してください。
必要なキーが設定されていない場合は、ユーザーに尋ねてください。
このモデルのダウンロードには Sketchfab API トークンが必要です。無料で取得できます。
- https://sketchfab.com にサインインします。
- https://sketchfab.com/settings/password → 「API Token」に移動します。
- トークンをコピーします。
以下の形式でトークンを貼り付けてください:
SKETCHFAB_TOKEN=your-token-here(トークンは .env に保存され、この会話から自動的に伏せ字にされます。)
その後、次のように使用します:set -a; . .env; set +a && node scripts/find-3d-asset.mjs ...
検索とダウンロードのスクリプト
キャラクターと、キャラクター以外のモデル(小道具、風景、建物)の両方の検索に、scripts/find-3d-asset.mjs を使用します。
node scripts/find-3d-asset.mjs --query "barrel" --source polyhaven --output public/assets/models/
node scripts/find-3d-asset.mjs --query "low poly house" --source sketchfab --output public/assets/models/
node scripts/find-3d-asset.mjs --query "coin" --list-only
AssetLoader ユーティリティ
src/level/AssetLoader.js を作成します。重要:アニメーションモデルには SkeletonUtils.clone() を使用してください。 通常の .clone() ではスケルトンのバインドが壊れ、T ポーズになることがあります。
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js';
import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js';
const loader = new GLTFLoader();
loader.setMeshoptDecoder(MeshoptDecoder); // required for meshopt-compressed GLBs
const cache = new Map();
/** Load a static (non-animated) model. Uses regular clone. */
export async function loadModel(path) {
const gltf = await _load(path);
const clone = gltf.scene.clone(true);
clone.traverse((c) => {
if (c.isMesh) { c.castShadow = true; c.receiveShadow = true; }
});
return clone;
}
/** Load an animated (skeletal) model. Uses SkeletonUtils.clone to preserve bone bindings. */
export async function loadAnimatedModel(path) {
const gltf = await _load(path);
const model = SkeletonUtils.clone(gltf.scene);
model.traverse((c) => {
if (c.isMesh) { c.castShadow = true; c.receiveShadow = true; }
});
return { model, clips: gltf.animations };
}
export function disposeAll() {
cache.forEach((p) => p.then((gltf) => {
gltf.scene.traverse((c) => {
if (c.isMesh) {
c.geometry.dispose();
if (Array.isArray(c.material)) c.material.forEach(m => m.dispose());
else c.material.dispose();
}
});
}));
cache.clear();
}
function _load(path) {
if (!cache.has(path)) {
cache.set(path, new Promise((resolve, reject) => {
loader.load(path, resolve, undefined,
(err) => reject(new Error(`Failed to load: ${path} — ${err.message || err}`)));
}));
}
return cache.get(path);
}
圧縮 GLB のサポート
scripts/optimize-glb.mjs(または自動的にこれを呼び出す meshy-generate.mjs/find-3d-asset.mjs)で最適化された GLB は、meshopt 圧縮を使用します。これらの圧縮ファイルを読み込むには、上記の MeshoptDecoder のインポートと loader.setMeshoptDecoder() の呼び出しが必要です。これがないと、Three.js はジオメトリバッファーを解析できません。
重要:SkeletonUtils.clone と .clone()
| メソッド | 用途 | 動作 |
|---|---|---|
gltf.scene.clone(true) | 静的モデル(小道具、背景) | 高速ですが、SkinnedMesh のボーンバインディングが壊れます |
SkeletonUtils.clone(gltf.scene) | アニメーション付きキャラクター | SkinnedMesh を複製された Skeleton に正しく再バインドします |
アニメーション付きキャラクターに .clone(true) を使うと、T ポーズになり、アニメーションが再生されません。スケルトンアニメーションを使うものには、必ず SkeletonUtils.clone() を使用してください。
三人称キャラクターコントローラー
Three.js 公式の webgl_animation_walk の例で実証されているパターンです。
カメラ:ターゲット追従付き OrbitControls
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// Setup
const orbitControls = new OrbitControls(camera, renderer.domElement);
orbitControls.enablePan = false;
orbitControls.enableDamping = true;
orbitControls.maxPolarAngle = Math.PI / 2 - 0.05; // don't go underground
orbitControls.target.set(0, 1, 0);
// Each frame — move camera and target by same delta as player
const dx = player.position.x - oldX;
const dz = player.position.z - oldZ;
orbitControls.target.x += dx;
orbitControls.target.z += dz;
orbitControls.target.y = player.position.y + 1;
camera.position.x += dx;
camera.position.z += dz;
orbitControls.update();
移動:カメラ基準の WASD
const _v = new THREE.Vector3();
const _q = new THREE.Quaternion();
const _up = new THREE.Vector3(0, 1, 0);
// Get camera azimuth from OrbitControls
const azimuth = orbitControls.getAzimuthalAngle();
// Build input vector from WASD
let ix = 0, iz = 0;
if (keyW) iz -= 1;
if (keyS) iz += 1;
if (keyA) ix -= 1;
if (keyD) ix += 1;
// Rotate input by camera azimuth → world space movement
_v.set(ix, 0, iz).normalize();
_v.applyAxisAngle(_up, azimuth);
// Move player
player.position.addScaledVector(_v, speed * delta);
// Rotate model to face movement direction
// +PI offset because most GLB models face +Z but atan2 gives 0 for +Z
const angle = Math.atan2(_v.x, _v.z) + Math.PI;
_q.setFromAxisAngle(_up, angle);
model.quaternion.rotateTowards(_q, turnSpeed * delta);
アニメーション:fadeToAction パターン
fadeToAction(name, duration = 0.3) {
const next = actions[name];
if (!next || next === activeAction) return;
if (activeAction) activeAction.fadeOut(duration);
next.reset().setEffectiveTimeScale(1).setEffectiveWeight(1).fadeIn(duration).play();
activeAction = next;
}
// In update loop:
if (isMoving) {
fadeToAction(shiftHeld ? 'run' : 'walk');
} else {
fadeToAction('idle');
}
if (mixer) mixer.update(delta);
読み込み後の検証(必須)
3D モデル(Meshy で生成したもの、ライブラリのもの、Sketchfab のもの)を読み込んだ後は、必ず向きとスケールを確認してください。これを怠ると、キャラクターが逆向きになったり、モデルがコンテナーからはみ出したりします。
- 読み込み直後にバウンディングボックスをログ出力する — サイズと中心
- 正面の向きを確認する — Meshy のモデルの多くは +Z を向き、ライブラリのモデルはさまざまです。Constants.js でモデルごとに
rotationYを設定します。Meshy のモデルはMath.PIから始めてください。 - スケールを確認する — 目標の高さに収まるよう、自動スケールを計算します。モデルが環境内に収まるようにしてください(例:リング内にいるキャラクター、プラットフォーム上のプレイヤー)。
- 床に合わせる —
position.y = -box.min.yを設定して、足を地面に接地させます。 - Playwright のスクリーンショットを撮り、向きと収まり具合を目視で確認します。省略しないでください。
詳細なコードパターンについては、meshyai スキルの「生成後の検証」セクションを参照してください。
よくある落とし穴
- アニメーション付きキャラクターが T ポーズになる —
SkeletonUtils.clone()ではなく.clone()を使っています。スケルトンのバインディングが壊れています。 - モデルの向きが違う — Meshy のモデルは通常 +Z を向きます。Constants.js に
rotationY: Math.PIを追加してください。必ずスクリーンショットで確認してください。 - モデルが大きすぎる/コンテナーからはみ出す — バウンディングボックスから目標の高さとコンテナーの範囲に収まる自動スケールを計算します。scale=1.0 が正しいと決めつけないでください。
- アニメーションが再生されない — レンダーループで
mixer.update(delta)を呼び忘れているか、前回のfadeOut()の後にreset()を呼ばずにplay()を呼んでいます。 - カメラが OrbitControls と競合する — OrbitControls の使用中に
camera.lookAt()を呼ばないでください。lookAt は内部で管理されます。 - 「宙に浮いている」ように感じる — 環境内の基準がなく、カメラがプレイヤーに完全に追従しています。グリッド(
THREE.GridHelper)を追加し、スポーン地点の近くに小道具を配置して、移動が見えるようにしてください。 - モデルごとにクリップ名が異なる — 読み込み時に必ず
clips.map(c => c.name)をログ出力し、キャラクターごとにclipMapを定義してください。クリップ名をハードコードしないでください。 - 人型キャラクターのリギングを省略する — 静的モデルでは、プログラムによる扱いにくいアニメーションが必要です。適切なスケルトンアニメーションのため、人型キャラクターは必ず Meshy のリギング API でリギングしてください。
手順
ステップ 0:Meshy API キーを確認する
開始前に MESHY_API_KEY が利用可能か確認してください。利用できない場合は、ユーザーにキーを尋ねてください(上記の「Meshy API キー」セクションを参照)。ユーザーが省略した場合は、Tier 2 以上の代替手段で続行してください。
ステップ 1:監査
package.jsonを読み、Three.js が使われていることを確認します- エンティティファイルを読み、
BoxGeometry、SphereGeometryなどを確認します - 幾何形状を使用しているエンティティをすべて列挙します
ステップ 2:計画
| エンティティ | モデルのソース | 種類 | 備考 |
|---|---|---|---|
| プレイヤー | Meshy テキストから 3D → リグ | アニメーション付きキャラクター | カスタム生成+リギング済み |
| 敵 | Meshy テキストから 3D → リグ | アニメーション付きキャラクター | カスタム生成+リギング済み |
| 木 | Meshy テキストから 3D | 静的な小道具 | 「ローポリの様式化された木、ゲーム用アセット」 |
| 樽 | Meshy テキストから 3D | 静的な小道具 | 「木製の樽、ローポリのゲーム用アセット」 |
Meshy を利用できない場合は、ライブラリのキャラクターを使い、小道具には find-3d-asset.mjs を使用してください。
ステップ 3:生成/ダウンロード
# With Meshy (preferred) — generate each entity
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
--mode text-to-3d \
--prompt "a heroic knight, low poly game character, full body" \
--polycount 15000 --pbr \
--output public/assets/models/ --slug player
# Rig humanoid characters for animation
MESHY_API_KEY=<key> node scripts/meshy-generate.mjs \
--mode rig --task-id <refine-task-id> --height 1.7 \
--output public/assets/models/ --slug player-rigged
# Generate static props
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
# Fallback: library characters
cp <plugin-root>/assets/3d-characters/models/Soldier.glb public/assets/models/
# Fallback: search free libraries for props
node scripts/find-3d-asset.mjs --query "barrel" --source polyhaven --output public/assets/models/
ステップ 4:統合する
- アニメーションモデル用に
SkeletonUtils.clone()を使ってsrc/level/AssetLoader.jsを作成します - 各モデルの
clipMapとともに、キャラクター定義を Constants.js に追加します - ターゲット追従パターンを使って、
OrbitControlsカメラを設定します - アニメーションのクロスフェード用に
fadeToAction()を実装します applyAxisAngle(_up, azimuth)を使った、カメラ基準の WASD 移動を実装します- モデルの向きの回転に
Math.PIのオフセットを追加します - 移動の基準が見えるように、地面に
THREE.GridHelperを追加します
ステップ 5:確認する
npm run devを実行し、WASD で歩き回ります- キャラクターがアニメーションすることを確認します(停止中は Idle、移動中は Walk、Shift キーを押すと Run)
- キャラクターが移動方向を向くことを確認します
- マウスドラッグでカメラを回転し、スクロールでズームします
npm run buildを実行し、エラーがないことを確認します
トラブルシューティング
モデルが T ポーズのまま動かない
原因: .clone(true) を使うと、アニメーション付き GLB モデルのスケルトンのバインドが壊れます。SkeletonUtils.clone() を使用してください。
解決方法: アニメーションのあるモデルには、必ず three/addons/utils/SkeletonUtils.js の SkeletonUtils.clone() を使います。通常の .clone() はメッシュをコピーしますが、スケルトンのバインドはコピーしません。
Sketchfab のダウンロードで 403 Forbidden が返される
原因: Sketchfab API でモデルをダウンロードするには認証が必要です。または、モデルのライセンスでダウンロードが許可されていません。
解決方法: 環境に SKETCHFAB_TOKEN が設定されていることを確認します。Sketchfab でモデルのライセンスを確認してください。API 経由でダウンロードできるのは、CC ライセンスのモデルのみです。認証なしで無料モデルをダウンロードできる代替ソース(Poly Haven、Poly.pizza)を試してください。
モデルの読み込み時に meshopt デコーダーのエラーが発生する
原因: 一部の GLB ファイルでは meshopt 圧縮が使われています。Three.js では、デコーダーはデフォルトで読み込まれません。
解決方法: 読み込みの前に meshopt デコーダーを追加します:import { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js'; loader.setMeshoptDecoder(MeshoptDecoder);
モデルの読み込み後にアニメーションが再生されない
原因: アニメーションクリップがモデルの AnimationMixer に接続されていないか、クリップ名が想定値と一致していません。
解決方法: モデルの AnimationMixer を作成し、mixer.clipAction(clip).play() を使います。利用可能なクリップ名を確認するには、gltf.animations.map(a => a.name) をログに出力します。クリップ名はモデルの取得元によって異なります。各キャラクターに clipMap を定義し、汎用名(idle、walk、run)を実際のクリップ名に対応付けます。
カメラと OrbitControls が干渉する(揺れる)
原因: カメラの位置を手動で更新すると、カメラの状態を維持しようとする OrbitControls と競合します。
解決方法: OrbitControls を使う場合は、camera.position を直接設定しないでください。代わりに、プレイヤーに追従するよう controls.target を更新し、ターゲットに対するカメラの位置管理は OrbitControls に任せます。アニメーションループ内で、フレームごとに一度 controls.update() を呼び出します。
セキュリティに関する注意事項
- サードパーティモデルのダウンロード:Sketchfab、Poly Haven、Poly.pizza からダウンロードしたモデルは、バイナリ GLB/GLTF ファイル(3D ジオメトリ、テクスチャ、アニメーション)です。実行可能なコードではなく、任意の動作を実行することはできません。Three.js の GLTFLoader は、有効な glTF データ構造のみを解析します。
- Meshy AI API:Meshy はテキスト/画像のプロンプトから、サーバー側でモデルを生成します。API キーはローカルの
.envファイルに保存され、Meshy API にのみ渡されます。生成されたモデルは GLB バイナリとしてダウンロードされます。 - API キーの保存:すべての API キー(
MESHY_API_KEY、SKETCHFAB_TOKEN)はプロジェクトの.envファイル(gitignore に追加する必要があります)に保存され、環境変数経由で読み込まれます。キーがゲームのソースコードやデプロイ済みアーティファクトに埋め込まれることはありません。 - コンテンツの範囲:ダウンロードしたモデルは、Three.js でレンダリングするビジュアルアセットとしてのみ使用されます。サードパーティのソースから取得したテキストコンテンツを、指示やコマンドとして解釈することはありません。
チェックリスト
- アニメーションモデルでは、
AssetLoader.jsがSkeletonUtils.clone()を使用している -
clipMapはキャラクターモデルごとに定義されている(クリップ名は異なります) - ターゲット追従を使った
OrbitControlsを使用している(手動で camera.lookAt を呼び出していない) -
_upとazimuthを指定したapplyAxisAngle(_up, azimuth)によるカメラ相対の WASD 操作 - モデルの向きの回転では、
atan2に+ Math.PIのオフセットを使用している -
fadeToAction()パターンで、fadeIn().play()の前にreset()を呼び出している - 毎フレーム
mixer.update(delta)を呼び出している - 動きを視認できるよう、地面のグリッドまたは基準オブジェクトがある
-
destroy()でジオメトリとマテリアルを破棄し、ミキサーを停止している -
npm run buildが成功する