给定以下两个向量:
Vector3 v3 = Vector3.one;
Vector2 v2 = Vector2.one;
这条线是模棱两可的:
v3 += v2; // Unity reports dimension ambiguity
而该任务不是:
v3 = v2; // Unity assigns despite different dimensions
为什么是这样?
给定以下两个向量:
Vector3 v3 = Vector3.one;
Vector2 v2 = Vector2.one;
这条线是模棱两可的:
v3 += v2; // Unity reports dimension ambiguity
而该任务不是:
v3 = v2; // Unity assigns despite different dimensions
为什么是这样?
Answers:
完整的问题消息:
错误CS0121:以下方法或属性之间的调用不明确:
UnityEngine.Vector2.operator +(UnityEngine.Vector2, UnityEngine.Vector2)' and
UnityEngine.Vector3.operator +(UnityEngine.Vector3,UnityEngine.Vector3)'
团结提供了一种隐式转换Vector3
到Vector2
,反之亦然。由于您可以同时使用+运算符,因此这会引起歧义。
在该操作中将您强制Vector2
转换为Vector3
显式,以便编译器知道使用UnityEngine.Vector3.operator +(UnityEngine.Vector3, UnityEngine.Vector3)
。
如果你很好奇,微软的特定错误文档是在这里。
编辑后进行编辑:
Vec3 += Vec2
出于与上述相同的原因,它是模棱两可的。想象一下Vec3 += Vec2
事实Vec3 = Vec3 + Vec2
。由于隐式转换Vec3 + Vec2
可以同时产生Vector2
和Vector3
作为答案,因此这就是为什么您必须指定所需的内容。
Vec3 = Vec2
不会有歧义,因为Vec2隐式转换为a Vector3
,然后分配给初始Vec3。因此,整个操作实际上Vector3 = Vector3
不需要您将Vec2强制转换为Vector3
手动操作。
让我重命名vars(为清楚起见):
Vector3 pos3d = new Vector3 (1f, 2f, 3f);
Vector2 pos2d = new Vector2 (1f, 2f);
这是因为pos3d + pos2d
该行的部分。这部分的确很模糊,而事实+=
并非如此。让我澄清为什么一个,为什么另一个。
在这条线
transform.position = pos3d + pos2d;
pos3d + pos2d
不管结果放在何处,编译器都会先尝试对表达式求值,然后再继续。
为此,系统首先尝试查找添加了Vector3和Vector2的任何公共静态函数,例如,以下可能的签名:
public static Vector3 operator +(Vector3 a, Vector2 b);
或例如以下可能的签名:
public static Vector2 operator +(Vector3 a, Vector2 b);
但是,API中没有任何这些签名,因此编译器尝试将参数“投射”到已知签名。
然后,编译器会找到这两个潜在的签名:
public static Vector3 operator +(Vector3 a, Vector3 b);
public static Vector2 operator +(Vector2 a, Vector2 b);
这些内容记录在这里:http : //docs.unity3d.com/ScriptReference/Vector3-operator_add.html 和此处:http : //docs.unity3d.com/ScriptReference/Vector2-operator_add.html
因此,有两种可能性:
因此,由于这两种转换都是可能的,因此可以将pos2d转换为Vector3,将pos3d转换为Vector2,然后编译器会找到可能的方法来编译相同的源代码(提供了自动隐藏的转换)。
可以将pos3d转换为Vector2并进行第二个签名,也可以将pos2d转换为Vector3并进行第一个签名。
由于首先对表达式pos3d + pos2d
求值,所以在考虑“将结果应用于何处”之前,编译器并不知道您将执行哪种类型的转换(作为编码器),就像编码器一样。
如果要转向3D,可以编写以下代码:
transform.position = pos3d + ( Vector3 )pos2d;
现在已经很清楚了,问题解决了:首先将pos2d移到Vector3类型的另一个对象中,然后将Vector3 + Vector3相加。只要有这个静态签名
public static Vector3 operator +(Vector3 a, Vector3 b);
可以使用,一点也不歧义。
另一方面,当你做
transform.position = pos3d;
transform.position += pos2d;
毫无疑问:第一行将Vector3分配给Vector3(毫无疑问)。
第二行相当于
transform.position = transform.position + pos2d;
具有特殊性,transform.position仅评估一次,因此考虑了类型,如您在此Microsoft页面中所看到的有关+=
运算符的那样:
https://msdn.microsoft.com/zh-CN/library/sa7629ew.aspx
此外,它还说:“ + =运算符不能直接重载,但是用户定义的类型可以重载+运算符(请参阅运算符)。” 因此,我们应该认为Vector3
的+=
运算符按照Microsoft所说的那样进行操作:
x += y
相当于
x = x + y
除了x仅被评估一次。+运算符的含义取决于x和y的类型(数字操作数的加法,字符串操作数的串联等)。
因此我们可以确定第二种方法会调用Vector3
具有签名的类的+操作数:
public static Vector3 operator +(Vector3 a, Vector3 b);
因此,由于无法将pos2d转换为Vector3,因此没有其他方法可以实现,这要归功于隐式隐式强制转换,该形式不能具有任何其他形式。
希望对大家有帮助!!
编辑
在Unity 5.0.1f1 Personal
用MonoDevelop-Unit 4.0.1
,亚历克斯M.说,该行:
transform.position = pos3d;
transform.position += pos2d;
仍然施放错误 "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)'"
所以实际上+ =使用两个签名
public static Vector3 operator +(Vector3 a, Vector3 b);
public static Vector2 operator +(Vector2 a, Vector2 b);
无论已经知道结果应放置在“哪里”的事实(我猜是因为输出Vector2可以将其强制转换为目标(Vector3),并且如果无法进行强制转换,也许,编译器会选择具有正确位置的那个)输出类型)。
感谢Alex M的观点。
pos3d += pos2d
(根据您编辑的问题)失败了,但是transform.position += pos2d
编译了(根据您上面的评论)?似乎奇怪的.position
是Vector3
-不能清楚地看到,如果这就是你的意思是什么。