Vectors are structs or so-called “data types”. They live on the stack and propagate as concrete data, instead of being considered through a pointer to something lying on a heap.
That said, it is completely reasonable to extract their components on the fly, do whatever is needed, then reassemble the new thing back.
For example
var myVec = new Vector3(.127f, .148f, .459f);
myVec.Normalize();
myVec = new Vector3(3f * Mathf.Round(myVec.x), 0f, Mathf.Round(myVec.z));
Debug.Log(myVec.ToString());
In my practice I’ve discovered a few interesting patterns that can be used with vectors in order to minimize repetition and allow better chaining of commands, so there are ways and ways to streamline the common vector manipulation. But there is nothing particularly wrong with deconstructing them and then building new ones on the fly. It just looks ugly sometimes (and may be prone to errors).
For example this is the above code written my way (perhaps not the most useful example but still…)
myVec = myVec.normalized.x_z().Lambda( (i,v) => Mathf.Round(v) ).ScaledBy(x: 3f);
Edit:
If you’re interested here the extensions are defined as follows (you must make an extension class for this to work, because we can’t edit the actual Vector3 class)
public static Vector3 x_z(this Vector3 v) => new Vector3(v.x, 0f, v.z);
public static Vector3 Lambda(this Vector3 v, Func<int, float, float> lambda)
=> new Vector3(lambda(0, v.x), lambda(1, v.y), lambda(2, v.z));
public static Vector3 ScaledBy(this Vector3 v, float x = 1f, float y = 1f, float z = 1f)
=> new Vector3(x * v.x, y * v.y, z * v.z);
// aka component-wise multiplication for two vectors
public static Vector3 ScaledBy(this Vector3 v, Vector3 other)
=> new Vector3(other.x * v.x, other.y * v.y, other.z * v.z);
All in all, if you want to multiply X by 3 in a readable manner, you can do this
myVec = myVec.ScaledBy(x: 3f);
But nothing stops you from implementing ScaleX or something similar. Whatever the case, you can’t avoid having to access the individual component, multiplying it, and then reassembling all components into a new Vector3 to reflect this change. This is how structs work.
Edit2:
In fact, because structs in C# are confusing for beginners, let me clarify the above example of multiplying the whole thing by 3, because it’s actually coded like this under the hood
public static Vector3 operator *(float lhs, Vector3 rhs) => new Vector3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
public static Vector3 operator *(Vector3 lhs, float rhs) => new Vector3(rhs * lhs.x, rhs * lhs.y, rhs * lhs.z);