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

Three.js如何按调用顺序加载GLTF模型并存储到对应数组中

问题原因

GLTFLoader的load方法是异步IO操作,回调执行顺序和调用顺序没有必然关联:体积小的模型会更快加载完成、更早触发回调执行push操作,最终数组顺序就是加载完成顺序,和你调用loadGLTF的顺序不一致,自然会出现下标错乱的问题。

解决方案

可以把加载逻辑封装成Promise,再用Promise.all统一处理,它的返回结果顺序和你传入Promise的顺序完全一致,天然就能保证下标和调用顺序对应,同时不会牺牲并发加载的性能。

修改后的代码如下:

var models = {
    tile: [],
    building: [],
    character: []
};

const loader = new GLTFLoader();
// 封装加载逻辑为返回Promise的函数
function loadGLTF(path, type){
    return new Promise((resolve, reject) => {
        loader.load(
            path,
            (gltf) => {
                gltf.scene.traverse( ( node ) => {
                    if( node.material ) {
                        node.material.metalness = 0;
                    }
                    if ( node.isMesh ) {
                        node.castShadow = type !== 'tile';
                        node.receiveShadow = true;
                    }
                } );
                // 加载成功直接返回处理好的gltf
                resolve(gltf);
            },
            (xhr) => {
                console.log( `${path} 加载进度: ${( xhr.loaded / xhr.total * 100 ).toFixed(2)}%` );
            },
            (error) => {
                console.log( `${path} 加载失败: `, error);
                reject(error);
            }
        );
    })
}

// 按预期顺序定义各类型的加载路径列表
const loadList = {
    tile: [
        'resources/models/tiles/tile_000.glb',
        'resources/models/tiles/tile_001.glb'
    ],
    building: [
        'resources/models/buildings/building_000.glb',
        'resources/models/buildings/building_001.glb',
        'resources/models/buildings/building_002.glb',
        'resources/models/buildings/building_003.glb',
        'resources/models/buildings/building_004.glb',
        'resources/models/buildings/building_005.glb',
        'resources/models/buildings/building_006.glb',
        'resources/models/buildings/building_007.glb',
        'resources/models/buildings/building_008.glb'
    ],
    character: [
        'resources/models/characters/Male.glb'
    ]
}

// 批量按顺序加载
async function loadAllModels() {
    for (const type in loadList) {
        // 生成该类型所有加载任务的Promise数组,顺序和loadList里的路径顺序一致
        const tasks = loadList[type].map(path => loadGLTF(path, type));
        // Promise.all返回结果顺序和tasks顺序完全一致,直接赋值即可保证下标对应
        models[type] = await Promise.all(tasks);
    }
    // 所有模型加载完成后执行后续逻辑,代替原来的checkLoad
    checkLoad();
}

// 调用加载入口启动加载
loadAllModels();

如果你不想调整原有调用写法,也可以给loadGLTF加第三个入参index,回调里直接用models[type][index] = gltf代替push,也能保证顺序,只是手动传下标容易出现书写错误,更推荐上述Promise方案。

内容的提问来源于stack exchange,提问作者Vardan Betikyan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 03:06:00