Babylon.js中GLTF模型无法添加动画问题求助
问题:Babylon.js中为GLTF模型添加动画无效,需创建两个动画
我是Babylon.js新手,尝试为Blender导出的monas.gltf模型添加动画但一直无效,代码如下,希望能实现两个动画效果,恳请帮忙解决。
import * as BABYLON from '@babylonjs/core'; import '@babylonjs/loaders/glTF'; import { Inspector } from '@babylonjs/inspector'; import '@babylonjs/core/Animations/animatable'; const canvas = document.getElementById('renderCanvas'); const engine = new BABYLON.Engine(canvas); const createScene = async function() { const scene = new BABYLON.Scene(engine); const camera = new BABYLON.ArcRotateCamera('camera', 1, 1, 8, new BABYLON.Vector3(0, 0, 0), scene); camera.attachControl(true); const light = new BABYLON.DirectionalLight('directionalLight', new BABYLON.Vector3(-2, -3, 0), scene); const shadowGenerator = new BABYLON.ShadowGenerator(900, light); BABYLON.SceneLoader.ImportMeshAsync('', '/', 'monas.gltf', scene).then((result) => { const monasMeshes = result.meshes; const monas = monasMeshes[0]; monas.scaling = new BABYLON.Vector3(0.25, 0.25, 0.25); console.log(monas); // Add rotation animation const animationBox = new BABYLON.Animation("rotationAnimation", "rotation.y", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE); const keys = []; keys.push({ frame: 0, value: 0 }); keys.push({ frame: 100, value: Math.PI * 2 }); animationBox.setKeys(keys); monas.animations.push(animationBox); scene.beginAnimation(monas, 0, 100, true); shadowGenerator.addShadowCaster(monas); }); return scene; }; const scene = await createScene(); engine.runRenderLoop(function() { scene.render(); }); window.addEventListener('resize', function() { engine.resize(); }); Inspector.Show(scene, {});
解决思路与修改方案
核心问题排查
- GLTF层级适配:直接取
meshes[0]可能选中的是模型根节点,但部分Blender导出的GLTF会将动画绑定到子网格或骨骼节点,需确保动画目标正确。 - 加载时机与回调嵌套:原代码用
then嵌套加载逻辑,容易出现动画绑定时机偏差,改用await更可靠。 - 相机控制参数错误:
attachControl(true)的参数顺序错误,第一个参数应为canvas元素,否则会导致交互异常。
实现双动画的修改代码
以下代码实现Y轴循环旋转和Z轴呼吸缩放两个动画,同时修正原代码的潜在问题:
import * as BABYLON from '@babylonjs/core'; import '@babylonjs/loaders/glTF'; import { Inspector } from '@babylonjs/inspector'; const canvas = document.getElementById('renderCanvas'); const engine = new BABYLON.Engine(canvas); const createScene = async function() { const scene = new BABYLON.Scene(engine); scene.clearColor = new BABYLON.Color4(0.1, 0.1, 0.1, 1); // 修正相机控制参数 const camera = new BABYLON.ArcRotateCamera('camera', 1, 1, 8, BABYLON.Vector3.Zero(), scene); camera.attachControl(canvas, true); const light = new BABYLON.DirectionalLight('directionalLight', new BABYLON.Vector3(-2, -3, 0), scene); light.intensity = 1.5; const shadowGenerator = new BABYLON.ShadowGenerator(1024, light); shadowGenerator.useBlurExponentialShadowMap = true; // 改用await加载,避免嵌套回调 const result = await BABYLON.SceneLoader.ImportMeshAsync('', '/', 'monas.gltf', scene); const monasRoot = result.meshes[0]; monasRoot.scaling = new BABYLON.Vector3(0.25, 0.25, 0.25); // 动画1:Y轴循环旋转 const rotateAnim = new BABYLON.Animation( "rotateY", "rotation.y", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE ); rotateAnim.setKeys([ { frame: 0, value: 0 }, { frame: 100, value: Math.PI * 2 } ]); // 动画2:Z轴呼吸缩放 const scaleAnim = new BABYLON.Animation( "scaleZ", "scaling.z", 15, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE ); scaleAnim.setKeys([ { frame: 0, value: 0.25 }, { frame: 50, value: 0.35 }, { frame: 100, value: 0.25 } ]); // 将两个动画添加到根节点 monasRoot.animations.push(rotateAnim, scaleAnim); // 同时播放两个动画,循环执行 scene.beginAnimation(monasRoot, 0, 100, true); // 遍历子网格添加阴影投射,确保所有可见网格都能产生阴影 monasRoot.getChildMeshes().forEach(mesh => { shadowGenerator.addShadowCaster(mesh); }); return scene; }; // 异步初始化场景 (async () => { const scene = await createScene(); engine.runRenderLoop(() => scene.render()); window.addEventListener('resize', () => engine.resize()); Inspector.Show(scene); })();
关键修改说明
- 模型加载逻辑优化:用
await替代then,确保动画在模型完全加载后再绑定,避免时机问题。 - 多动画绑定:直接将多个动画实例推入节点的
animations数组,调用beginAnimation即可同时播放。 - 阴影适配:遍历模型子网格添加阴影投射,解决原代码仅绑定根节点导致无阴影的问题。
- 调试建议:如果动画仍不生效,打开Babylon Inspector查看模型层级,确认动画绑定的节点是否为实际可变换的网格/骨骼节点。
内容的提问来源于stack exchange,提问作者Salt
相关产品推荐
相关产品推荐

