I often like to give myself a little convenience method:

 Vector3 CameraRelativeFlatten(Vector3 input, Vector3 localUp)
 {
 // If this script is on your camera object, you can use this.transform instead.
 Transform cam = Camera.main.transform;

 // The first part creates a rotation looking into the ground, with
 // "up" matching the camera's look direction as closely as it can. 
 // The second part rotates this 90 degrees, so "forward" input matches 
 // the camera's look direction as closely as it can in the horizontal plane.
 Quaternion flatten = Quaternion.LookRotation(
 -localUp, 
 cam.forward
 )
 * Quaternion.Euler(Vector3.right * -90f);

 // Now we rotate our input vector into this frame of reference
 return flatten * input;
 }

When I have an input in controller space, I can use this convert it to a direction in the world horizontal plane, relative to the camera:

 Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));

 Vector3 worldSpaceInput = CameraRelativeFlatten(input, Vector3.up);

If we wanted, we could also use a local surface normal instead of `Vector3.up` to get our input parallel to an arbitrary tilted surface, instead of always in the XZ plane.

Since we're rotating the input vector, the length is preserved, so we won't just chop off the portion of a vector that was digging into the surface, slowing our forward-back movement relative to left-right.