You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Three Fiber场景中导入带预加载动画的自定义模型?

导入带预加载动画的自定义模型到React Three Fiber场景

问题背景

已成功导出带基础动画的立方体,但已知GLTFExporter无法导出包含材质动画的内容,现需将带有预加载动画的自定义GLTF/GLB模型导入到现有React Three Fiber场景中。


解决方案步骤

1. 使用@react-three/drei的useGLTF加载模型

@react-three/drei提供了便捷的模型加载工具,能自动处理GLTF/GLB模型的材质、网格和动画数据。若未安装依赖,先执行:

npm install @react-three/drei

2. 加载并播放模型动画

替换原有的Model组件,改为加载自定义模型,并利用AnimationMixer播放预加载的动画:

import React, { useRef, useEffect, useState } from 'react';
import { Canvas, useFrame, useThree } from '@react-three/fiber';
import { OrbitControls, useGLTF } from '@react-three/drei';
import * as THREE from 'three';
import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter';
import './App.css';

function CustomModel() {
    const meshRef = useRef();
    // 替换为你的GLTF/GLB模型路径
    const { scene, animations } = useGLTF('/your-custom-model.glb');
    const { scene: rootScene } = useThree();
    const [mixer] = useState(() => new THREE.AnimationMixer());
    const clock = new THREE.Clock();
    const [exported, setExported] = useState(false);

    useEffect(() => {
        if (scene && animations.length > 0) {
            // 获取模型主网格(根据你的模型结构调整,若模型有层级需遍历找到目标网格)
            const modelMesh = scene.children[0];
            meshRef.current = modelMesh;
            modelMesh.name = 'customAnimatedModel';

            // 播放预加载的第一个动画剪辑
            const action = mixer.clipAction(animations[0], modelMesh);
            action.play();

            // 动画完成后触发导出(可选)
            setTimeout(() => {
                if (!exported) {
                    handleExport(rootScene, animations[0]);
                    setExported(true);
                }
            }, animations[0].duration * 1000);
        }
    }, [mixer, exported, rootScene, scene, animations]);

    useFrame(() => {
        const delta = clock.getDelta();
        mixer.update(delta);
    });

    const handleExport = (scene, clip) => {
        const gltfExporter = new GLTFExporter();
        const options = {
            binary: true,
            animations: [clip],
        };
        gltfExporter.parse(scene, function (result) {
            if (result instanceof ArrayBuffer) {
                saveArrayBuffer(result, 'exported-model.glb');
            } else {
                const output = JSON.stringify(result, null, 2);
                console.log(output);
                saveString(output, 'exported-model.gltf');
            }
        }, function (error){
            console.log("导出出错");
            console.log(error);
        }, options);
        
        const link = document.createElement('a');
        link.style.display = 'none';
        document.body.appendChild(link);
        
        function save(blob, filename) {
            link.href = URL.createObjectURL(blob);
            link.download = filename;
            link.click();
        }
        function saveString(text, filename) {
            save(new Blob([text], { type: 'text/plain' }), filename);
        }
        function saveArrayBuffer(buffer, filename) {
            save(new Blob([buffer], { type: 'application/octet-stream' }), filename);
        }
    };

    return <primitive object={scene} ref={meshRef} />;
}

// 预加载模型,优化加载体验
useGLTF.preload('/your-custom-model.glb');

export default function App() {
    return (
        <>
            <Canvas camera={{ position: [-8, 5, 8] }}>
                <ambientLight intensity={0.5} />
                <CustomModel />
                <OrbitControls />
            </Canvas>
        </>
    );
}

3. 关键注意事项

  • 确保自定义模型为标准GLTF 2.0/GLB格式,预加载动画需符合GLTF规范(支持位置、旋转、缩放动画;材质动画目前GLTFExporter导出受限,但导入播放不受影响)。
  • 模型路径需正确:本地文件放在public目录下,远程资源直接填写完整URL。
  • 若模型包含多个动画剪辑,可通过animations数组索引切换播放目标,或添加交互逻辑实现动画切换。

内容的提问来源于stack exchange,提问作者Marc Newsom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 15:54:54