diff --git a/src/assets/gltf-model-import.js b/src/assets/gltf-model-import.js index 67af01da..b5ac87d3 100644 --- a/src/assets/gltf-model-import.js +++ b/src/assets/gltf-model-import.js @@ -328,7 +328,11 @@ function rewriteGltfResourceUris(gltfJson, files) { }; } function cloneTemplateScene(scene) { - return scene.clone(true); + // Use SkeletonUtils.clone so that SkinnedMesh.skeleton.bones are remapped + // to the cloned hierarchy. A plain scene.clone(true) leaves the bones array + // pointing at the original loader's nodes, which are gone after parsing, + // making every skinned mesh invisible at runtime. + return cloneSkeleton(scene); } function cloneMaterial(material) { return material.clone(); diff --git a/src/assets/gltf-model-import.ts b/src/assets/gltf-model-import.ts index aa819167..383aae16 100644 --- a/src/assets/gltf-model-import.ts +++ b/src/assets/gltf-model-import.ts @@ -453,7 +453,11 @@ function rewriteGltfResourceUris( } function cloneTemplateScene(scene: Group): Group { - return scene.clone(true); + // Use SkeletonUtils.clone so that SkinnedMesh.skeleton.bones are remapped + // to the cloned hierarchy. A plain scene.clone(true) leaves the bones array + // pointing at the original loader's nodes, which are gone after parsing, + // making every skinned mesh invisible at runtime. + return cloneSkeleton(scene) as Group; } function cloneMaterial(material: Material): Material {