How do I get my character's left hand IK position to not be behind by a frame when holding weapons?

At the moment, I’m getting the end effector world position for my character’s left hand from the weapon skeleton’s left hand location socket.

The weapon itself is attached to the character’s right hand.

So when my animation is playing, my animation event graph is retreiving this position. Then the animation updates in the anim graph. But the left hand position is from a frame ago before the animation was updated, so my character’s left hand lags behind by a frame since it depends on the right hand. Also the weapon might be animating. If I have a shotgun and am cocking it, the left hand should follow the sliding part.

The only way I can think of fixing this is by running the anim graph in multiple passes. Once for the right hand, then for the left hand, but I’m not sure if this is currently possible.

Or would I have to implement a native AnimInstance?

I’m sure there are many others who are trying similar things with weapons and hand holding.

I’m thinking about adding a custom Skeleton Control.

I’m already using a helper IK bone. I’m going to try setting the IK bone to the location of the socket in the weapon mesh itself. I’ll make the control take in another mesh, and a bone/socket name to align to. I’ll probably call it something like Copy Transform From Another Mesh’s Bone.

I’ll need to make sure the weapon attachment animates before the hands though so the sliding part of the shotgun will be updated before the left hand gets updated.

I have exactly the same problem and find it very frustrating to see that even after 1.5 years no one at Epic seems to find this situation in any way problematic. Do they think no one needs hand IKs to snap hands to weapons or other objects that are moving? Updating sockets only after the whole anim graph ran through is simply not feasible in any game that needs proper hand IKs. (And even for legs is a lag of one frame simply unacceptable)

I actually ended up doing exactly what I said above. It works quite well enough but I really do wish there was a better way since my solution feels a bit hacky.

It’s difficult to switch between having a prop held in the left hand and have the right hand move to the right spot or holding in the right hand and having the left hand be in the right spot. I’m limited to only one or the other and am choosing the right hand as dominant due to the way I have to structure the anim graph.

I actually ended up doing exactly what I said above. It works quite well enough but I really do wish there was a better way since my solution feels a bit hacky.

It’s difficult to switch between having a prop held in the left hand and have the right hand move to the right spot or holding in the right hand and having the left hand be in the right spot. I’m limited to only one or the other and am choosing the right hand as dominant due to the way I have to structure the anim graph.

I copy pasted code from the copy bone skeletal control but added code to get the transform from an attached scene component. You can’t animate the destination socket on the attached mesh though since that’ll be a frame late as well. As I understand it there’s no way to force an attached skeletal mesh to animate before the parent its attached to since the world transforms of the bones will be different.

void FAnimNode_CopyBoneFromSceneComponent::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
	check(OutBoneTransforms.Num() == 0);

	// Pass through if we're not doing anything.
	if (!bCopyTranslation && !bCopyRotation && !bCopyScale)
	{
		return;
	}

	// Get component space transform for source and current bone.
	const FBoneContainer& BoneContainer = MeshBases.GetPose().GetBoneContainer();
	FCompactPoseBoneIndex TargetBoneIndex = TargetBone.GetCompactPoseIndex(BoneContainer);
	FTransform CurrentBoneTM = MeshBases.GetComponentSpaceTransform(TargetBoneIndex);
	FTransform SourceCSTM;
	
	//if it's an attachment to the currently animating skeleton, get the transform relative to the attachment point
	//ComponentToWorld on the source mesh will be a frame late so we must get it this way
	//Otherwise be sure to set the other mesh to update before this one with tick prerequesites.
	//And if you have a circular dependency, then god help you :D.  That is until there's some way to update animation poses in multiple passes, maybe?
	if (SourceComponent->AttachParent == SkelComp)
	{
		//code is based off the get socket transform code in skeletal mesh component, only that doesn't work here since it's a frame late, I think.  We must use the FCSPose object.
		//I wonder if it's possible to refactor this somehow eventually so the code can be reused
		//get the offset socket's transform relative to the end bone
		int32 AttachBoneIndex = SkelComp->GetBoneIndex(SourceComponent->AttachSocketName);

		//transform of the component in our component space
		FTransform SourceMeshAttachmentCSTM;

		if (AttachBoneIndex != INDEX_NONE)
		{
			SourceMeshAttachmentCSTM = MeshBases.GetComponentSpaceTransform(BoneContainer.MakeCompactPoseIndex(FMeshPoseBoneIndex(AttachBoneIndex)));
		}
		else
		{
			USkeletalMeshSocket const* const Socket = SkelComp->GetSocketByName(SourceComponent->AttachSocketName);
			AttachBoneIndex = SkelComp->GetBoneIndex(Socket->BoneName);

			if (Socket && AttachBoneIndex != INDEX_NONE)
			{
				SourceMeshAttachmentCSTM = (FTransform(Socket->RelativeRotation, Socket->RelativeLocation, Socket->RelativeScale) * MeshBases.GetComponentSpaceTransform(BoneContainer.MakeCompactPoseIndex(FMeshPoseBoneIndex(AttachBoneIndex))));
			}
		}

		SourceCSTM = FTransform(SourceComponent->RelativeRotation, SourceComponent->RelativeLocation, SourceComponent->RelativeScale3D) * SourceMeshAttachmentCSTM;

        if (SourceSocket != NAME_None)
        {
            SourceCSTM = SourceComponent->GetSocketTransform(SourceSocket, RTS_Component) * SourceCSTM;
        }
	}
	else
	{
		//convert the source bone transform from its component space to this component space
		SourceCSTM = SkelComp->ComponentToWorld.Inverse();

        if (SourceSocket != NAME_None)
        {
            SourceCSTM = SourceComponent->GetSocketTransform(SourceSocket, RTS_World) * SourceCSTM;
        }
	}

	// Copy individual components
	if (bCopyTranslation)
	{
		CurrentBoneTM.SetTranslation(SourceCSTM.GetTranslation());
	}

	if (bCopyRotation)
	{
		CurrentBoneTM.SetRotation(SourceCSTM.GetRotation());
	}

	if (bCopyScale)
	{
		CurrentBoneTM.SetScale3D(SourceCSTM.GetScale3D());
	}

	// Output new transform for current bone.
	OutBoneTransforms.Add(FBoneTransform(TargetBoneIndex, CurrentBoneTM));
}

Well, I actually need to have our weapons animated, as well as having the left hand put onto the grip or magazine via IK. It’s something that’s easily possible in any other engine I ever used, because it didn’t expect IKs to be applied in the exact same function than the rest of the animations.

I am currently working on a system to call a second anim pass at the end of the frame, where I run a secondary anim graph from code with just the IKs in it. Its a big engine rework, but it isn’t the first of Unreals strange implementations I had to refactor.