Let me rename the vars (for clarity):
Vector3 pos3d = new Vector3 (1f, 2f, 3f);
Vector2 pos2d = new Vector2 (1f, 2f);
Answer
It is because of the section pos3d + pos2d
of the line. This part is really ambiguous while the +=
is not. Let me clarify why one and why the other.
Analysis 1
In this line
transform.position = pos3d + pos2d;
the compiler first tries to evaluate the expression pos3d + pos2d
before proceeding, regardless of where the result is going to be placed.
To do so, the system first tries to find any public static function that adds a Vector3 plus a Vector2, for example this possible signature:
public static Vector3 operator +(Vector3 a, Vector2 b);
or for example this possible signature:
public static Vector2 operator +(Vector3 a, Vector2 b);
Nevertheless there is not any of those signatures in the API so the compiler tries to "cast" parameters to known signatures.
Then the compiler finds those two potential signatures:
public static Vector3 operator +(Vector3 a, Vector3 b);
public static Vector2 operator +(Vector2 a, Vector2 b);
These are documented here:
http://docs.unity3d.com/ScriptReference/Vector3-operator_add.html
and here:
http://docs.unity3d.com/ScriptReference/Vector2-operator_add.html
So there are two possibilities:
So as both castings are possible, pos2d can be casted to a Vector3 and pos3d is castabale into a Vector2, the compiler then finds to possible ways to compile the same source code (provided automatic hidden castings are in place).
It is either possible to cast pos3d into Vector2 and proceed with the second signature, or either cast pos2d into Vector3 and proceed with the first signature.
As the expression pos3d + pos2d
is evaluated first, before taking in consideration "where the result will be applied" then the compiler does not know what cast would you -as coder- like it to perform.
If you want to move towards 3D, you can write this:
transform.position = pos3d + ( Vector3 )pos2d;
and the problem is gone, as now it is clear: first move pos2d into another object of type Vector3, then do the sum of Vector3 + Vector3. Provided that there is this static signature
public static Vector3 operator +(Vector3 a, Vector3 b);
available, that one will be used with no ambiguity at all.
Analysis 2
On the other hand, when you do
transform.position = pos3d;
transform.position += pos2d;
there is no ambiguity: The first line assigns a Vector3 into a Vector3 (no doubts).
The second line is equivalent to
transform.position = transform.position + pos2d;
with the particularity the transform.position is only evaluated once, and therefore the type is taken in consideration, as you can see in this Microsoft page about the +=
operator:
https://msdn.microsoft.com/en-us/library/sa7629ew.aspx
It in addition says "The += operator cannot be overloaded directly, but user-defined types can overload the + operator (see operator)." so we should think the Vector3
's +=
operator acts as described by microsoft where it says:
x += y
is equivalent to
x = x + y
except that x is only evaluated once. The meaning of the + operator
depends on the types of x and y (addition for numeric operands,
concatenation for string operands, and so forth).
so we can be sure the second approach invokes the + operand of the Vector3
class, which has the signature:
public static Vector3 operator +(Vector3 a, Vector3 b);
so there is not any other way to achieve this than converting the pos2d into a Vector3 thanks to an implicit hidden cast that cannot be of any other form.
Hope to help!!
Edit
In Unity 5.0.1f1 Personal
with MonoDevelop-Unit 4.0.1
, as Alex M. says, the lines:
transform.position = pos3d;
transform.position += pos2d;
still cast the error "Assets/Scripts/CubeScript.cs(15,27): error CS0121: The call is ambiguous between the following methods or properties: 'UnityEngine.Vector2.operator +(UnityEngine.Vector2, UnityEngine.Vector2)' and 'UnityEngine.Vector3.operator +(UnityEngine.Vector3, UnityEngine.Vector3)'"
so really the += is using both signatures
public static Vector3 operator +(Vector3 a, Vector3 b);
public static Vector2 operator +(Vector2 a, Vector2 b);
regardless of the fact of already knowing "where" the result shall be placed (I guess because outputting a Vector2 is castable to the destination (Vector3) and if that cast was not possible probably, maybe, the compiler would choose the one with the proper output type).
Thanks for the point Alex M.