When BlendRootMotionBasedOnRootBone is false, the LayeredBlendPerBone is aggregating root motion of the child poses ontop of the base pose root motion. (ie. if the first child pose's blend weight is 1, you get 100% root motion from the first child but also 100% from the base pose).
The expected behaviour is that the root motion of the child poses should instead be blended with the base pose. (ie. if the first child pose's blend weight is 1, you get 100% of root motion from the first child and 0% from the base pose).
The code responsible for this is:
float RootMotionWeight = 0.f; const float RootMotionClearWeight = bBlendRootMotionBasedOnRootBone ? 0.f : 1.f; if (IsLODEnabled(Context.AnimInstanceProxy)) { GetEvaluateGraphExposedInputs().Execute(Context); for (int32 ChildIndex = 0; ChildIndex < BlendPoses.Num(); ++ChildIndex) { const float ChildWeight = BlendWeights[ChildIndex]; if (FAnimWeight::IsRelevant(ChildWeight)) { if (bHasRelevantPoses == false) { // Update cached data now we know we might be valid UpdateCachedBoneData(Context.AnimInstanceProxy->GetRequiredBones(), Context.AnimInstanceProxy->GetSkeleton()); // Update weights FAnimationRuntime::UpdateDesiredBoneWeight(DesiredBoneBlendWeights, CurrentBoneBlendWeights, BlendWeights); bHasRelevantPoses = true; if(bBlendRootMotionBasedOnRootBone && !CurrentBoneBlendWeights.IsEmpty()) { const float NewRootMotionWeight = CurrentBoneBlendWeights[0].BlendWeight; if(NewRootMotionWeight > ZERO_ANIMWEIGHT_THRESH) { RootMotionWeight = NewRootMotionWeight; RootMotionBlendPose = CurrentBoneBlendWeights[0].SourceIndex; } } } const float ThisPoseRootMotionWeight = (ChildIndex == RootMotionBlendPose) ? RootMotionWeight : RootMotionClearWeight; BlendPoses[ChildIndex].Update(Context.FractionalWeightAndRootMotion(ChildWeight, ThisPoseRootMotionWeight)); } } } // initialize children const float BaseRootMotionWeight = 1.f - RootMotionWeight; if (BaseRootMotionWeight < ZERO_ANIMWEIGHT_THRESH) { BasePose.Update(Context.FractionalWeightAndRootMotion(1.f, BaseRootMotionWeight)); } else { BasePose.Update(Context); }
Because
bBlendRootMotionBasedOnRootBone is false in this setup, we never set RootMotionWeight so it is always zero. Meaning that BaseRootMotionWeight (which is passed as the root motion weight into the BasePose pose link) is always 1 so we always get 100% of the root motion from that pose.
If/when we fix this we should be careful of any behaviour change for users who may be relying on the broken behaviour.
I am not able to find world outliner how to enable it?
How can i modify the param name in EQS node
Undefined sysmbol: typeinfo for AActor when cross-compile linux dedicated server on windows
How to achieve HLSL Multiple Render Target in Material blueprints?
Delay nodes occasionally don't fire the "Completed" output in a nativized build
What method is used to fill polygonal regions when drawing spline mesh at run time?
There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-187223 in the post.
0 |
Component | UE - Anim - Runtime |
---|
Created | May 27, 2023 |
---|---|
Resolved | Jun 1, 2023 |
Updated | Jun 5, 2023 |