When you import and set up a GLTF scene containing transformation animations that apply to multiple objects, they're played in sync out of the box:


When the animations in question use multiple armatures and skinned meshes, however, this isn't the case:


In this scenario, only the first of the skinned objects receives the animations in question.
This test file used a cloned armature, but duplicated armatures produce the same result.
I also tried manually setting up a separate AnimationMixer() on the second skinned mesh using the imported AnimationClips and didn't get that to work, but I'm not sure if that particular issue was user error.
Inspecting the file manually and re-importing it into Blender shows that it is structured correctly such that the animations are associable to both armatures and skinned meshes, and maybe should reasonably work out of the box the same way as non-armature animations:


(The Blender importer splits each animation into a named NLA track per object.)
TwoArmatures.gltf
{"asset":{"generator":"Khronos glTF Blender I/O v1.2.75","version":"2.0"},"scene":0,"scenes":[{"name":"Scene","nodes":[1,2,4,5]}],"nodes":[{"name":"Bone","translation":[0,2,0]},{"mesh":0,"name":"Cube","skin":0},{"children":[0],"name":"Armature","translation":[-2,0,0]},{"name":"Bone","translation":[0,2,0]},{"mesh":1,"name":"Cube.001","skin":1},{"children":[3],"name":"Armature.001","translation":[2,0,0]}],"animations":[{"channels":[{"sampler":0,"target":{"node":0,"path":"translation"}},{"sampler":1,"target":{"node":0,"path":"rotation"}},{"sampler":2,"target":{"node":0,"path":"scale"}},{"sampler":3,"target":{"node":3,"path":"translation"}},{"sampler":4,"target":{"node":3,"path":"rotation"}},{"sampler":5,"target":{"node":3,"path":"scale"}}],"name":"Down","samplers":[{"input":13,"interpolation":"LINEAR","output":14},{"input":13,"interpolation":"LINEAR","output":15},{"input":13,"interpolation":"LINEAR","output":16},{"input":13,"interpolation":"LINEAR","output":17},{"input":13,"interpolation":"LINEAR","output":18},{"input":13,"interpolation":"LINEAR","output":19}]},{"channels":[{"sampler":0,"target":{"node":0,"path":"translation"}},{"sampler":1,"target":{"node":0,"path":"rotation"}},{"sampler":2,"target":{"node":0,"path":"scale"}},{"sampler":3,"target":{"node":3,"path":"translation"}},{"sampler":4,"target":{"node":3,"path":"rotation"}},{"sampler":5,"target":{"node":3,"path":"scale"}}],"name":"Up","samplers":[{"input":13,"interpolation":"LINEAR","output":20},{"input":13,"interpolation":"LINEAR","output":21},{"input":13,"interpolation":"LINEAR","output":22},{"input":13,"interpolation":"LINEAR","output":23},{"input":13,"interpolation":"LINEAR","output":24},{"input":13,"interpolation":"LINEAR","output":25}]}],"materials":[{"doubleSided":true,"emissiveFactor":[0,0,0],"name":"Material","pbrMetallicRoughness":{"baseColorFactor":[0.800000011920929,0.800000011920929,0.800000011920929,1],"metallicFactor":0,"roughnessFactor":0.4000000059604645}}],"meshes":[{"name":"Cube","primitives":[{"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2,"JOINTS_0":3,"WEIGHTS_0":4},"indices":5,"material":0}]},{"name":"Cube","primitives":[{"attributes":{"POSITION":7,"NORMAL":8,"TEXCOORD_0":9,"JOINTS_0":10,"WEIGHTS_0":11},"indices":5,"material":0}]}],"skins":[{"inverseBindMatrices":6,"joints":[0],"name":"Armature"},{"inverseBindMatrices":12,"joints":[3],"name":"Armature.001"}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"max":[-1,1,1],"min":[-3,-1,-1],"type":"VEC3"},{"bufferView":1,"componentType":5126,"count":24,"type":"VEC3"},{"bufferView":2,"componentType":5126,"count":24,"type":"VEC2"},{"bufferView":3,"componentType":5123,"count":24,"type":"VEC4"},{"bufferView":4,"componentType":5126,"count":24,"type":"VEC4"},{"bufferView":5,"componentType":5123,"count":36,"type":"SCALAR"},{"bufferView":6,"componentType":5126,"count":1,"type":"MAT4"},{"bufferView":7,"componentType":5126,"count":24,"max":[3,1,1],"min":[1,-1,-1],"type":"VEC3"},{"bufferView":8,"componentType":5126,"count":24,"type":"VEC3"},{"bufferView":9,"componentType":5126,"count":24,"type":"VEC2"},{"bufferView":10,"componentType":5123,"count":24,"type":"VEC4"},{"bufferView":11,"componentType":5126,"count":24,"type":"VEC4"},{"bufferView":12,"componentType":5126,"count":1,"type":"MAT4"},{"bufferView":13,"componentType":5126,"count":1,"max":[0.041666666666666664],"min":[0.041666666666666664],"type":"SCALAR"},{"bufferView":14,"componentType":5126,"count":1,"type":"VEC3"},{"bufferView":15,"componentType":5126,"count":1,"type":"VEC4"},{"bufferView":16,"componentType":5126,"count":1,"type":"VEC3"},{"bufferView":17,"componentType":5126,"count":1,"type":"VEC3"},{"bufferView":18,"componentType":5126,"count":1,"type":"VEC4"},{"bufferView":19,"componentType":5126,"count":1,"type":"VEC3"},{"bufferView":20,"componentType":5126,"count":1,"type":"VEC3"},{"bufferView":21,"componentType":5126,"count":1,"type":"VEC4"},{"bufferView":22,"componentType":5126,"count":1,"type":"VEC3"},{"bufferView":23,"componentType":5126,"count":1,"type":"VEC3"},{"bufferView":24,"componentType":5126,"count":1,"type":"VEC4"},{"bufferView":25,"componentType":5126,"count":1,"type":"VEC3"}],"bufferViews":[{"buffer":0,"byteLength":288,"byteOffset":0},{"buffer":0,"byteLength":288,"byteOffset":288},{"buffer":0,"byteLength":192,"byteOffset":576},{"buffer":0,"byteLength":192,"byteOffset":768},{"buffer":0,"byteLength":384,"byteOffset":960},{"buffer":0,"byteLength":72,"byteOffset":1344},{"buffer":0,"byteLength":64,"byteOffset":1416},{"buffer":0,"byteLength":288,"byteOffset":1480},{"buffer":0,"byteLength":288,"byteOffset":1768},{"buffer":0,"byteLength":192,"byteOffset":2056},{"buffer":0,"byteLength":192,"byteOffset":2248},{"buffer":0,"byteLength":384,"byteOffset":2440},{"buffer":0,"byteLength":64,"byteOffset":2824},{"buffer":0,"byteLength":4,"byteOffset":2888},{"buffer":0,"byteLength":12,"byteOffset":2892},{"buffer":0,"byteLength":16,"byteOffset":2904},{"buffer":0,"byteLength":12,"byteOffset":2920},{"buffer":0,"byteLength":12,"byteOffset":2932},{"buffer":0,"byteLength":16,"byteOffset":2944},{"buffer":0,"byteLength":12,"byteOffset":2960},{"buffer":0,"byteLength":12,"byteOffset":2972},{"buffer":0,"byteLength":16,"byteOffset":2984},{"buffer":0,"byteLength":12,"byteOffset":3000},{"buffer":0,"byteLength":12,"byteOffset":3012},{"buffer":0,"byteLength":16,"byteOffset":3024},{"buffer":0,"byteLength":12,"byteOffset":3040}],"buffers":[{"byteLength":3052,"uri":"data:application/octet-stream;base64,AACAvwAAgD8AAIA/AACAvwAAgD8AAIC/AABAwAAAgD8AAIC/AABAwAAAgD8AAIA/AABAwAAAgD8AAIA/AABAwAAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AABAwAAAgD8AAIC/AABAwAAAgL8AAIC/AABAwAAAgL8AAIA/AABAwAAAgD8AAIA/AABAwAAAgL8AAIA/AABAwAAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AABAwAAAgL8AAIC/AABAwAAAgD8AAIC/AAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAvwAAAAAAAACAAACAvwAAAAAAAACAAACAvwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAACAPwAAAAAAAACAAACAPwAAAAAAAACAAACAPwAAAAAAAACAAACAPwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAgPwAAgD4AACA/AAAAPwAAYD8AAAA/AABgPwAAgD4AACA/AAAAAAAAwD4AAAAAAADAPgAAgD4AACA/AACAPgAAID8AAEA/AADAPgAAQD8AAMA+AACAPwAAID8AAIA/AAAAPgAAgD4AAAA+AAAAPwAAwD4AAAA/AADAPgAAgD4AACA/AACAPgAAwD4AAIA+AADAPgAAAD8AACA/AAAAPwAAID8AAAA/AADAPgAAAD8AAMA+AABAPwAAID8AAEA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcAAACAPwAAAIAAAAAAAAAAgAAAAIAAAIA/AAAAgAAAAAAAAAAAAAAAgAAAgD8AAACAAAAAQAAAAAAAAACAAACAPwAAQEAAAIA/AACAPwAAQEAAAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIC/AACAPwAAQEAAAIC/AACAPwAAQEAAAIA/AACAPwAAgD8AAIA/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAPwAAgD8AAIA/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAvwAAQEAAAIC/AACAvwAAQEAAAIC/AACAPwAAQEAAAIA/AACAPwAAQEAAAIC/AACAPwAAQEAAAIC/AACAvwAAQEAAAIA/AACAvwAAQEAAAIA/AACAvwAAQEAAAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIA/AACAvwAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAgL8AAAAAAAAAgAAAgL8AAAAAAAAAgAAAgL8AAAAAAAAAgAAAgL8AAAAAAAAAgAAAAAAAAIC/AAAAgAAAAAAAAIC/AAAAgAAAAAAAAIC/AAAAgAAAAAAAAIC/AAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAgD8AAAAAAAAAgAAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAID8AAIA+AAAgPwAAAD8AAGA/AAAAPwAAYD8AAIA+AAAgPwAAAAAAAMA+AAAAAAAAwD4AAIA+AAAgPwAAgD4AACA/AABAPwAAwD4AAEA/AADAPgAAgD8AACA/AACAPwAAAD4AAIA+AAAAPgAAAD8AAMA+AAAAPwAAwD4AAIA+AAAgPwAAgD4AAMA+AACAPgAAwD4AAAA/AAAgPwAAAD8AACA/AAAAPwAAwD4AAAA/AADAPgAAQD8AACA/AABAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAACAAAAAAAAAAIAAAACAAACAPwAAAIAAAAAAAAAAAAAAAIAAAIA/AAAAgAAAAMAAAAAAAAAAgAAAgD+rqio9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPw=="}]}
TwoBoxes.gltf
{"asset":{"generator":"Khronos glTF Blender I/O v1.2.75","version":"2.0"},"scene":0,"scenes":[{"name":"Scene","nodes":[0,1]}],"nodes":[{"mesh":0,"name":"Cube","translation":[-2,0,0]},{"mesh":0,"name":"Cube.001","translation":[2,4,0]}],"animations":[{"channels":[{"sampler":0,"target":{"node":0,"path":"translation"}},{"sampler":1,"target":{"node":1,"path":"translation"}}],"name":"Down","samplers":[{"input":4,"interpolation":"STEP","output":5},{"input":4,"interpolation":"STEP","output":6}]},{"channels":[{"sampler":0,"target":{"node":0,"path":"translation"}},{"sampler":1,"target":{"node":1,"path":"translation"}}],"name":"Up","samplers":[{"input":4,"interpolation":"STEP","output":7},{"input":4,"interpolation":"STEP","output":8}]}],"meshes":[{"name":"Cube.001","primitives":[{"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3}]}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"max":[1,1,1],"min":[-1,-1,-1],"type":"VEC3"},{"bufferView":1,"componentType":5126,"count":24,"type":"VEC3"},{"bufferView":2,"componentType":5126,"count":24,"type":"VEC2"},{"bufferView":3,"componentType":5123,"count":36,"type":"SCALAR"},{"bufferView":4,"componentType":5126,"count":1,"max":[0.041666666666666664],"min":[0.041666666666666664],"type":"SCALAR"},{"bufferView":5,"componentType":5126,"count":1,"type":"VEC3"},{"bufferView":6,"componentType":5126,"count":1,"type":"VEC3"},{"bufferView":7,"componentType":5126,"count":1,"type":"VEC3"},{"bufferView":8,"componentType":5126,"count":1,"type":"VEC3"}],"bufferViews":[{"buffer":0,"byteLength":288,"byteOffset":0},{"buffer":0,"byteLength":288,"byteOffset":288},{"buffer":0,"byteLength":192,"byteOffset":576},{"buffer":0,"byteLength":72,"byteOffset":768},{"buffer":0,"byteLength":4,"byteOffset":840},{"buffer":0,"byteLength":12,"byteOffset":844},{"buffer":0,"byteLength":12,"byteOffset":856},{"buffer":0,"byteLength":12,"byteOffset":868},{"buffer":0,"byteLength":12,"byteOffset":880}],"buffers":[{"byteLength":892,"uri":"data:application/octet-stream;base64,AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAgPwAAQD8AAMA+AABAPwAAwD4AAIA/AAAgPwAAgD8AACA/AAAAPwAAwD4AAAA/AADAPgAAQD8AACA/AABAPwAAID8AAIA+AADAPgAAgD4AAMA+AAAAPwAAID8AAAA/AAAgPwAAAAAAAMA+AAAAAAAAwD4AAIA+AAAgPwAAgD4AAAA+AACAPgAAAD4AAAA/AADAPgAAAD8AAMA+AACAPgAAID8AAIA+AAAgPwAAAD8AAGA/AAAAPwAAYD8AAIA+AAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcAq6oqPQAAAMAAAAAAAAAAgAAAAEAAAAAAAAAAgAAAAMAAAIBAAAAAgAAAAEAAAIBAAAAAgA=="}]}
In this scenario, only the first of the skinned objects receives the animations in question.
This is caused by https://github.com/mrdoob/three.js/issues/15087, and would be fixed by https://github.com/mrdoob/three.js/pull/16639. three.js requires that animated objects have unique names, because animation targets them by name. In this example, the model contains two bones each with the name "Bone". You can also work around the issue by giving each bone a unique name in Blender.
Another option is to attach an AnimationMixer to each armature in the model and animate them separately, then there is no conflict between the names.
@donmccurdy
Right. Thank you for the quick response and the clear and helpful explanation.
In my actual project, I'm not sure I can give the armatures unique bone names because they share a single datablock that's linked from a library file. I could write a short Python script to localize them and automatically deduplicate their names— But they also share NLA and action data, so I'm not sure if renaming bones might mess up their animations in Blender.
I suspect I may have to start using multiple AnimationMixer()s at some point eventually anyway to implement new features in my project, but using it as a work-around for this case where the built-in behaviour is already so close seems like it'd add a lot of code and overhead for the result. Also, just from looking in my browser's Javascript console, I'm not sure I see any good way to associate the AnimationClip()s from the imported GLTF file to the armature nodes in the scene. Each KeyframeTrack() seems to be tied to only the name of the affected bones, and not those bones' containing armatures, implying that to use separate AnimationMixer()s with arbitrary GLTF files, I'd have to (1) have a separate configuration file specifying which animation tracks affect which objects, which would be cumbersome, (2) write some sort of heuristic for trying to detect when animation data refers to the bones of an armature, which could be unreliable, or (3) try to assign a different AnimationMixer() to every single bone in every armature, which would be messy and seems like it could cause performance issues.
I don't really have an explicit point to make with this comment, because I don't know enough about three.js to know what the point should be. This is just context for this issue within my workflow.
But they also share NLA and action data, so I'm not sure if renaming bones might mess up their animations in Blender.
This isn't a problem — Blender does not depend on the objects' names to target animation correctly.
I'm not sure I see any good way to associate the AnimationClip()s from the imported GLTF file to the armature nodes in the scene.
Yes, it depends on the project whether this would work. If you know that the objects have different NLA Tracks with different names, and that the same NLA Track doesn't affect multiple armatures, you could just divide the list of animations into groups and use them with different armatures. For example:
// Assuming you've assigned prefixed names for NLA tracks in Blender....
const animsChar1 = animations.filter((clip) => clip.name.includes('Char1'));
const animsChar2 = animations.filter((clip) => clip.name.includes('Char2'));
const char1 = scene.getObjectByName('Char1');
const char2 = scene.getObjectByName('Char2');
const mixer1 = new AnimationMixer(char1);
const mixer2 = new AnimationMixer(char2);
mixer1.clipAction(animsChar1[0]).play();
This would work well if you want to control animation on each object separately, anyway. If you really want to handle it all as one big animation, then it would be better to find some way of ensuring everything has unique names.
I would not go as far as trying to split individual KeyframeTracks out of a clip, or creating mixer for every bone.
This isn't a problem — Blender does not depend on the objects' names to target animation correctly.
As far as I can tell, it does for bones, at least when the actions are stored as NLA tracks. Renaming a bone causes it to stay in its current transformation and be unaffected when I switch the NLA track. Restoring the original name lets the the NLAs work again as they did before.
EDIT: Hm. Actually, it seems it does rely on names for bones, not just for action targeting but also for skinning targeting via vertex group names— But it usually renames vertex group names automatically, and it renames associated action bone targets automatically if the armature in question has an active (or NLA Edit Mode) in the Dopesheet window.
So my workflow isn't looking quite as simple as it would be if #16639 (or a better alternative) were merged, but it's still reasonable to automate.
Actually, honestly, I'm not sure what it's doing. The NLAs do stop working immediately after renaming, but are fine again after reloading the file or viewing them in edit mode, so it seems to just take some time to update its displayed scene to the renamed targets. Anyway, that's a Blender workaround, and so long as the workflow is fine, I don't suppose it's super-relevant to three.js.