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

Three.js中为导入的Blender玫瑰模型绑定Cannon-es物理体时的位置更新问题

问题分析与解决方案

你遇到的核心问题是GLTF模型加载是异步操作,你的代码把物理体创建和objectsToUpdate数组的更新放在了加载回调外面,这时候rose变量根本没被正确赋值(回调里的rose是局部变量,外面的作用域拿不到它),所以在tick函数里访问object.roseAndBody.rose.position时,这个rose是undefined,自然会提示不存在position属性。

修复步骤

  1. 将物理体逻辑移到加载回调内:确保只有当模型成功加载并获取到rose对象后,才创建对应的物理体并将两者关联存入更新数组。
  2. 同步物理体初始位置:利用函数传入的px, py, pz设置物理体初始位置,贴合你调用函数时的预期,而不是固定的(0,3,0)。
  3. 优化变量作用域:彻底避免异步导致的变量未初始化问题。

修改后的代码

const objectsToUpdate = [] 
const createRose = (px, py, pz, rx, ry, rz) =>{ 
    gltfLoader.load('/models/pieces/Rose.glb', (gltf) =>{ 
        let rose = gltf.scene.children[0] 
        rose.position.set(px, py, pz) 
        rose.rotation.set(rx, ry, rz) 
        scene.add(rose) 

        // Cannon.js 物理体 - 移到回调内,确保rose已有效存在
        const shape = new CANNON.Cylinder(2, 1, 5, 20) 
        const body = new CANNON.Body({ 
            mass: 1, 
            position: new CANNON.Vec3(px, py, pz), // 使用传入的初始位置
            shape: shape, 
            material: defaultMaterial 
        }) 
        world.addBody(body) 

        // 存入更新数组 - 此时rose是有效的模型对象
        objectsToUpdate.push({ 
            roseAndBody:{ 
                rose: rose, 
                body: body 
            } 
        }) 
    }) 
}

你的tick函数代码不需要修改,现在objectsToUpdate里的每一项都包含有效的rose模型和对应的物理体,位置与四元数的同步逻辑就能正常运行了。

额外提示

  • 如果你要加载多个玫瑰,这个逻辑依然适用,每个模型加载完成后才会绑定物理体,不会再出现未初始化的问题。
  • 若尝试其他物理库(比如Ammo.js),核心逻辑完全一致:必须等待模型异步加载完成后,再创建物理体并建立关联。
  • 可以在加载过程中添加简单的加载提示(比如一个旋转的Three.js网格),避免加载时的空白等待,提升体验。

内容的提问来源于stack exchange,提问作者Cody Luketic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 20:13:09