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

Three.js加载多重复制GLTF角色的动画归属识别问题

解决方案

Blender端准备:确保角色与动作独立绑定

  1. 复制角色时分离骨骼数据:复制包含网格和骨骼的角色集合后,选中新角色的骨骼,在右侧属性面板的「骨骼数据」面板中,点击数据块名称旁的「用户」图标,选择「复制数据块」——这会让新角色拥有独立的骨骼数据,避免与原角色共享。
  2. 复制并绑定动作到新骨骼:打开NLA编辑器,选中原角色的动作轨道,按Ctrl+D复制轨道;进入姿态模式,选中新角色的骨骼,在动作编辑器的「关联到」下拉菜单中选择新角色的骨骼数据块,确保动作绑定到新骨骼。
  3. 给动作添加唯一标识:将每个动作重命名为「角色ID_动作名」格式,比如Char001_Idle、Char001_StartAiming,便于后续在Three.js中区分归属。
  4. 导出GLB:选中所有角色,在导出选项中勾选「动画>导出动画」,确保所有绑定好的动作都被正确导出。

Three.js端:将动画分配到对应角色对象

加载GLB文件后,通过动画轨道的骨骼路径识别归属角色,将动画添加到角色对象的animations数组中,并初始化对应的AnimationMixer:

import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

const loader = new GLTFLoader();
loader.load('your-characters.glb', (gltf) => {
  // 遍历场景中的角色网格(带骨骼的Mesh)
  gltf.scene.traverse((obj) => {
    if (obj.isMesh && obj.skeleton) {
      // 初始化角色的动画数组和混合器
      obj.animations = [];
      obj.mixer = new THREE.AnimationMixer(obj);

      // 从根骨骼名称提取角色ID(假设根骨骼命名为「CharXXX_Hips」)
      const rootBoneName = obj.skeleton.bones[0].name;
      const charId = rootBoneName.split('_')[0];

      // 匹配并分配对应动画
      gltf.animations.forEach((clip) => {
        // 检查动画轨道是否属于当前角色
        const isCharAnimation = clip.tracks.some(track => 
          track.name.startsWith(`${charId}_`)
        );
        if (isCharAnimation) {
          obj.animations.push(clip);
          // 可选:预创建动作(根据需要)
          // obj.mixer.clipAction(clip).play();
        }
      });
    }
  });

  // 将场景添加到场景树
  scene.add(gltf.scene);
});

之后播放角色动画时,直接调用角色对象的混合器即可:

// 播放Char001的Idle动画
const char001 = scene.getObjectByName('Char001_Mesh');
const idleClip = char001.animations.find(clip => clip.name.endsWith('Idle'));
char001.mixer.clipAction(idleClip).play();

额外优化

如果需要创建100个角色,建议用Blender脚本批量生成角色、复制骨骼数据、绑定动作并统一命名,避免手动操作的繁琐和错误。

内容的提问来源于stack exchange,提问作者Martin Sonesson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 09:05:20