Animation 'Replace' blend mode

Hello guys,
I looking for a solution to play complete animation over other animations. For example, shoottingAni affects the upper half of the body(only keyframes from Spine bone) and runAni in the background.
I tried some ways:

  1. Set runAni.setEffectiveWeight(0) and shoottingAni.setEffectiveWeight(1) => upperbody ok, but bottombody reset to default pose.

  2. Set runAni.setEffectiveWeight(0.1) and shoottingAni.setEffectiveWeight(1) => bottom body ok, but upper body blend together makes the wrong animation.

  3. Change transform of bones following shoottingAni. I write some code on the update function(after the update animation) for the change transform of bone. This way looks doing the right way, but the animation is not smooth, I can continue working with tween to make it better but I see that FPS is down from 60 to 35 after running this code, and not back to 60. I can’t understand why. Maybe because call “getBoneByName” too much?

  4. THREE.AdditiveAnimationBlendMode” Apply this blend mode to shoottingAni, and everything transforms of bone looks like “Addition”. But I want to “Replace”.

Thanks for any suggestions and ideas, I really appreciate any help.

Not 100% sure if I understood correctly - but if this is the kind of effect you’re looking for (legs and aiming moving independently - then after loading your animations, you can just filter the bones to which said animation will be applied (ex. aiming animation only to top body, walking only bottom body, idle animation to both etc.):

if (filterBones) {
  // NOTE Run animation only for these specific bones
  const filteredBindings = [];
  const filteredInterpolants = [];
  const bindings = action._propertyBindings || [];
  const interpolants = action._interpolants || [];

  bindings.forEach((propertyMixer, index) => {
    const { binding } = propertyMixer;

    if ((binding && binding.targetObject && !filterBones.includes(binding.targetObject.name))) {
      return;
    } else {
      filteredBindings.push(propertyMixer);
      filteredInterpolants.push(interpolants[index]);
    }
  });

  action._propertyBindings = filteredBindings;
  action._interpolants = filteredInterpolants;
} else if (excludeBones) {
  // NOTE Run animation for all except these specific bones
  const filteredBindings = [];
  const filteredInterpolants = [];
  const bindings = action._propertyBindings || [];
  const interpolants = action._interpolants || [];

  bindings.forEach((propertyMixer, index) => {
    const { binding } = propertyMixer;

    if (!(binding && binding.targetObject && excludeBones.includes(binding.targetObject.name))) {
      filteredBindings.push(propertyMixer);
      filteredInterpolants.push(interpolants[index]);
    }
  });

  action._propertyBindings = filteredBindings;
  action._interpolants = filteredInterpolants;
}

The filtering then has to be done only one time, when the animation is loaded.

1 Like

Beautiful, It’s exactly what I need. Thank you so so much <3.
Just note that I can’t find ‘targetObject’ in PropertyMixer(my version is r149), so I used 'binding.node.name' instead of 'binding.targetObject.name'