To simplify the answer, Vector3
is a custom struct
provided by the UnityEngine
namespace. When we create custom class
or struct
types, we must also define its operators. As such, there is no default logic for the >=
operator. As pointed out by Evgeny Vasilyev, _rect_tfm.position == _positionB
makes sense, as we can directly check the Vector3.x
, Vector3.y
and Vector3.z
values. _rect_tfm.position >= _positionB
does not make as much sense, due to the fact that a Vector3
is represented by three separate values.
We could overload the Vector3
class to contain the suitable operators in theory, but that seems rather complicated. Instead, it would be easier to simply extend the Vector3
class with a suitable method. That being said, it seems that your intending to use this logic for movement. As such, you might find it much easier to use the Vector3.Lerp
method; if so, read further below.
Adding extension methods to Vector3
As previously mentioned, applying <=
or >=
to a Vector3
is often illogical. For movement, you probably want to read further for the Vector3.Lerp
method. That said, you might want to apply the <=
=>
arithmetic for other reasons, so I will give you an easy alternate.
Instead of applying the logic of Vector3 <= Vector3
or Vector3 >= Vector3
, I propose extending the Vector3
class to include methods for isGreaterOrEqual(Vector3 other)
and isLesserOrEqual(Vector3)
. We can add extension methods to a struct
or class
by declaring them in a static
class that does not inherit. We also include the target class
or struct
as the first parameter, using the this
keyword. Note that in my example, I assume that you mean to ensure that all three main values (x
, y
and z
) are all greater or equal, or lesser or equal, respectively. You can provide your own logic, here, as you require.
public static class ExtendingVector3
{
public static bool IsGreaterOrEqual(this Vector3 local, Vector3 other)
{
if(local.x >= other.x && local.y >= other.y && local.z >= other.z)
{
return true;
}
else
{
return false;
}
}
public static bool IsLesserOrEqual(this Vector3 local, Vector3 other)
{
if(local.x <= other.x && local.y <= other.y && local.z <= other.z)
{
return true;
}
else
{
return false;
}
}
}
When we attempt to call these methods from the Vector3
class, local
will represent the Vector3
instance we are calling the method from. You will note that the methods are static
; extension methods must be static
, but you still have to call them from an instance. Given the above extension methods, you can now apply them directly to your Vector3
types.
Vector3 left;
Vector3 right;
// Is left >= right?
bool isGreaterOrEqual = left.IsGreaterOrEqual(right);
// Is left <= right?
bool isLesserOrEqual = left.IsLesserOrEqual(right);
Moving Vector3
with Vector3.Lerp
Calling the Vector3.Lerp
method allows us to determine the exact position between two Vector3
values at a given time. An added benefit of this method is that the Vector3
will not overshoot its target. Vector3.Lerp
takes three parameters; the start position, the end position, and the current position represented as a value between 0 and 1. It outputs the resulting position as a Vector3
, which we can directly set as the current position.
Solving your problem, I propose using Vector3.Lerp
to move to a targetPosition
. After calling the Move
method in each Update
, we can check if we have reached said target; Lerp.Vector3
will not overshoot, so transform.position == targetPosition
becomes reliable. We can now check the position, and change the targetPosition
to leftPosition
or rightPosition
to reverse the movement, accordingly.
public Vector3 leftPosition, rightPosition;
public float speed;
public Vector3 targetPosition;
private void Awake()
{
targetPosition = rightPosition;
}
private void Update()
{
Move();
if(transform.position == targetPosition)
{
// We have arrived at our intended position. Move towards the other position.
if(targetPosition == rightPosition)
{
// We were moving to the right; time to move to the left.
targetPosition = leftPosition;
}
else
{
// We were moving to the left; time to move to the right.
targetPosition = rightPosition;
}
}
}
private void Move()
{
// First, we need to find out the total distance we intend to move.
float distance = Vector3.Distance(transform.position, targetPosition);
// Next, we need to find out how far we intend to move.
float movement = speed * Time.deltaTime;
// We find the increment by simply dividing movement by distance.
// This will give us a decimal value. If the decimal is greater than
// 1, we are moving more than the remaining distance. Lerp
// caps this number at 1, which in turn, returns the end position.
float increment = movement / distance;
// Lerp gives us the absolute position, so we pass it straight into our transform.
transform.position = Vector3.Lerp(transform.position, targetPosition, increment);
}
You can see this demonstrated in the following animation. I translate the blue cube with Vector3.LerpUnclamped
, which gives us a similar result to simple unchecked translation. I translate the red cube using Vector3.Lerp
. Left unchecked, the blue cube moves off into oblivion; while the red cube stops exactly where I intend it to. You can read more about this type of movement in the Stack Overflow documentation.

Bools
like_atPosA
and_atPosB
. Inevitably, you'll make a mistake keeping them both in sync, and it'll lead to bugs. It's better to make anenum
containing all the positions (A, B, perhaps others in the future), and using that \$\endgroup\$>=
mean for aVector3
? Compare component-wise? That would not be a total ordering. Consider usingVector3.MoveTowards
\$\endgroup\$var vec1 = new Vector3(1, 0, 0)
andvar vec2 = new Vector3(0, 1 ,0)
. Isvec1 >= vec2
true or false? \$\endgroup\$