Introduction
What Is Save&Use Cached Pose
Node?
UE4 has already provided a Save Cached Pose
for one-to-many link in Anim Graph like this:
We can use a Use Save Cached Pose
node to refer a Save Cached Pose
node.
Not-recommended Way
It actually surprised me that we can use Reroute Node
to achieve one to many
pose link like this:
And it does work.
However, I’ve talked to Epic about this issue and it turned out that this is considered as a bug. Moreover, this could cause multiple evaluation&update, which might result in some strange issue.
In short, just don’t use it.
What’s Deep Inside ?
Let’s take a look at function FAnimNode_SaveCachedPose::Evaluate_AnyThread
1 | void FAnimNode_SaveCachedPose::Evaluate_AnyThread(FPoseContext& Output) |
It is guaranteed to have referred nodes to be evaluated at most once per frame by synchronizing evaluation counters. And this is truly useful when building complex animation blueprints.
The Sadness of Space-Conversion
This method only works, however, in Local Spaces.
This means that we need extra some space transform nodes if we want to achieve one-to-many
pose link in component space like this:
Space convert node is not that cheap since every bone is required to perform a space conversion.
Thus we made some modification to use cached pose
and save cached pose
node.
Modification Details
FAnimNode_SaveCachedPose
and UAnimGraphNode_SaveCachedPose
Add a FComponentSpacePoseLink
to FAnimNode_SaveCachedPose
, and of course, a boolean property to determine if this node is under component space or local space.
Moreover, a FCSPose<FCompactPose>
property is also needed. Because a FCompactPose
does not have ComponentSpaceFlags
, which is supposed to be passed from Save cahced pose
node to Use cached pose
node.
Obviously we need to override EvaluateComponentSpace_AnyThread
function, which is simply the same as Evaluate_AnyThread
.
1 | void FAnimNode_SaveCachedPose::EvaluateComponentSpace_AnyThread(FComponentSpacePoseContext& Output) |
Of course, don’t forget to handle CacheBones_AnyThread
, Initialize_AnyThread
and PostGraphUpdate
function.
As for UAnimGraphNode_SaveCachedPose
, we need to override its CustomizePinData
and PostEditChangeProperty
function:
1 | void UAnimGraphNode_SaveCachedPose::CustomizePinData(UEdGraphPin* Pin, FName SourcePropertyName, int32 ArrayIndex) const |
FAnimNode_UseCachedPose
and UAnimGraphNode_UseCachedPose
First of all, we should add a FComponentSpacePoseLink
property, just like LinkToCachingNode
.
Then override EvaluateComponentSpace_AnyThread
function that simply evaluate the component space pose link.
Still, we need to override CreateOutputPins
function to eventually create component space out pins.
1 | void UAnimGraphNode_UseCachedPose::CreateOutputPins() |
Link Pose Together
We need to link FAnimNode_UseCachedPose::LinkToCachingNode_Component
to FAnimNode_SaveCachedPose::ComponentPose
.
To achieve this, we should modify FAnimBlueprintCompilerContext::ProcessUseCachedPose
function
1 | if (UAnimGraphNode_SaveCachedPose* AssociatedSaveNode = SaveCachedPoseNodes.FindRef(UseCachedPose->SaveCachedPoseNode->CacheName)) |
Last but not least, we should handle such warning:
In order to solve this issue, we should modify FAnimBlueprintCompilerContext::ProcessAnimationNode
function:
1 | if (!bConsumed && (SourcePin->Direction == EGPD_Input)) |
And that’s all! Everything is good to go:
Enjoy this feature.