With root motion, it does seem more complicated. Facing the same issue and what worked with non root motion was taking the flattened velocity Vector of the character (to the character’s up or ground normal) and divide it by the speed that they’re supposed to move to get the normalized direction. I then inverse it to the character’s transform and assign the value to the animator.
This got me a pretty comfortable animation for my movement but doesn’t do well for root motion as this is driven entirely by the velocity that already gets set before hand / last frame. Old post or not I hope this helps someone in some way.
//get current velocity
Vector3 vel = rigidbody.velocity;
//remove the parts of the velocity we don't need
Vector3 movePlaneNormal = isGrounded ? groundNormal : transform.up;
vel = Vector3.ProjectOnPlane(vel, movePlaneNormal);
//clamp the velocity for direction, providing smooth(ish) value
vel /= targetSpeed;
vel = Vector3.ClampMagnitude(vel, 1);
Vector3 animDirection = transform.InverseTransformVector(vel);
//apply a 'modifier' for blend tree (walk, jog, sprint)
// 0.5 for walk, 1 for jog,1.5 for sprint
//handle condition
animDirection *= mod;
//assign values to animator
animator.SetFloat("moveX", animDirection.x);
animator.SetFloat("moveZ", animDirection.z);