Hi, in answer to your specific question:
> This leads to the question in the title: is it guaranteed that the PostEvaluateAnimation event can obtain the positions of bones after animation is applied?
No, if you call GetSocketLocation from PostEvaluateAnimation you will get the bone transform from the previous frame. The reason for this is that PostEvaluateAnimation is called via USkeletalMesh::DoInstancePostEvaluation. And that method is called prior to FinalizeAnimationUpdate, which is where the double-buffered transforms on the mesh are flipped. If you call GetSocketLocation before FinalizeAnimationUpdate has been called, you will index into the previous frame’s transform buffer on the mesh (ie. ComponentSpaceTransformsArray[CurrentReadComponentTransforms]).
If you want to add code or blueprint that is guaranteed to run after the transforms on the mesh have been updated, the best approach is likely to add a tick prerequisite on the mesh. This will guarantee that the mesh has been updated for the current frame, and so the double-buffered transforms have been flipped so that GetSocketLocation returns the expected data.
Let me know if this works for you.