Weights mix groups playing at once: group.weight (or an animatable's, or scene.beginWeightedAnimation) scales each contribution; the default -1 means unweighted, so set it on every group you mix. Blending eases from the current pose into a newly started animation (enableBlending, blendingSpeed), and additive groups (AnimationGroup.MakeAnimationAdditive) layer a gesture on top. Three foxes, weighted from Walk to Run as in Crossfading Actions, at 0.3 seconds:
<canvas id="view" style="width: 620px; height: 140px"></canvas>
<script src="https://cdn.jsdelivr.net/npm/babylonjs@9.28.0/babylon.js"></script>
<script>
(async () => {
const cdn = 'https://cdn.jsdelivr.net/npm/babylonjs-loaders@9.28.0/';
await BABYLON.Tools.LoadScriptAsync(cdn + 'babylonjs.loaders.min.js');
const engine = new BABYLON.Engine(view, true, {}, true);
const scene = new BABYLON.Scene(engine);
scene.clearColor = BABYLON.Color4.FromHexString('#eceff1ff');
scene.createDefaultLight();
const target = new BABYLON.Vector3(0, 0.22, 0);
new BABYLON.ArcRotateCamera('side', -Math.PI / 2, 1.45, 1.25, target, scene).fov = 0.6;
const container = await BABYLON.LoadAssetContainerAsync('fox.glb', scene);
[1, 0.5, 0].forEach((walkWeight, i) => {
const { rootNodes, animationGroups } = container.instantiateModelsToScene();
const holder = new BABYLON.TransformNode(`fox${i}`, scene); // scale and turn the copy
rootNodes[0].parent = holder;
holder.scaling.setAll(0.005); // centimeters to meters
holder.position.x = (i - 1) * 0.95; // side by side, side view
holder.rotation.y = Math.PI / 2;
const [, walk, run] = animationGroups; // Survey, Walk, Run
walk.weight = walkWeight;
run.weight = 1 - walkWeight;
for (const group of [walk, run]) group.start(true).goToFrame(18, true).pause();
});
scene.executeWhenReady(() => engine.runRenderLoop(() => scene.render()));
scene.onAfterRenderObservable.add(() => { window.__done = scene.getFrameId() > 5; });
})();
</script>
Seek with goToFrame(frame, true), or each group writes its full pose and the last wins. Moving the weights from Walk to Run over half a second is a crossfade; syncAllAnimationsWith() keeps the strides in step.