Pozwól mi zmienić nazwę vars (dla jasności):
Vector3 pos3d = new Vector3 (1f, 2f, 3f);
Vector2 pos2d = new Vector2 (1f, 2f);
Odpowiedź
Jest to spowodowane odcinkiem pos3d + pos2d
linii. Ta część jest naprawdę dwuznaczna, podczas gdy +=
nie jest. Pozwól mi wyjaśnić, dlaczego jedno i dlaczego drugie.
Analiza 1
W tej linii
transform.position = pos3d + pos2d;
kompilator najpierw próbuje ocenić wyrażenie pos3d + pos2d
przed kontynuowaniem, niezależnie od tego, gdzie wynik ma zostać umieszczony.
Aby to zrobić, system najpierw próbuje znaleźć dowolną publiczną funkcję statyczną, która dodaje Vector3 i Vector2, na przykład tę możliwą sygnaturę:
public static Vector3 operator +(Vector3 a, Vector2 b);
lub na przykład ten możliwy podpis:
public static Vector2 operator +(Vector3 a, Vector2 b);
Niemniej jednak w interfejsie API nie ma żadnych tych podpisów, więc kompilator próbuje „rzutować” parametry na znane podpisy.
Następnie kompilator znajduje te dwa potencjalne podpisy:
public static Vector3 operator +(Vector3 a, Vector3 b);
public static Vector2 operator +(Vector2 a, Vector2 b);
Są one udokumentowane tutaj:
http://docs.unity3d.com/ScriptReference/Vector3-operator_add.html
i tutaj:
http://docs.unity3d.com/ScriptReference/Vector2-operator_add.html
Istnieją więc dwie możliwości:
Aby oba castingi były możliwe, pos2d można rzutować na Vector3, a pos3d jest castabale na Vector2, kompilator następnie znajduje możliwe sposoby na skompilowanie tego samego kodu źródłowego (pod warunkiem, że automatyczne ukryte castingi są na miejscu).
Możliwe jest albo rzutowanie pos3d na Vector2 i przejście do drugiego podpisu, albo albo rzutowanie pos2d na Vector3 i przejście do pierwszego podpisu.
Gdy wyrażenie pos3d + pos2d
jest oceniane najpierw, zanim weźmie się pod uwagę „gdzie zostanie zastosowany wynik”, kompilator nie wie, jaką obsadę - jak programista - wykona.
Jeśli chcesz przejść do 3D, możesz napisać to:
transform.position = pos3d + ( Vector3 )pos2d;
problem zniknął, ponieważ teraz jest jasne: najpierw przenieś pos2d do innego obiektu typu Vector3, a następnie wykonaj sumę Vector3 + Vector3. Pod warunkiem, że istnieje ten podpis statyczny
public static Vector3 operator +(Vector3 a, Vector3 b);
dostępne, ten będzie używany bez żadnych dwuznaczności.
Analiza 2
Z drugiej strony, kiedy to zrobisz
transform.position = pos3d;
transform.position += pos2d;
nie ma dwuznaczności: pierwsza linia przypisuje Vector3 do Vector3 (bez wątpliwości).
Druga linia odpowiada
transform.position = transform.position + pos2d;
ze szczególnym uwzględnieniem transform.position jest oceniany tylko raz, dlatego też brany jest pod uwagę typ, jak można zobaczyć na tej stronie Microsoft o +=
operatorze:
https://msdn.microsoft.com/en-us/library/sa7629ew.aspx
Ponadto napisano: „Operatora + = nie można bezpośrednio przeciążać, ale typy zdefiniowane przez użytkownika mogą przeciążać operatora + (patrz operator)”. więc powinniśmy myśleć Vector3
„s +=
operator działa w sposób opisany przez Microsoft, gdzie jest napisane:
x += y
jest równa
x = x + y
z wyjątkiem tego, że x jest obliczany tylko raz. Znaczenie operatora + zależy od typów xiy (dodawanie dla operandów numerycznych, konkatenacja dla operandów łańcuchowych i tak dalej).
więc możemy być pewni, że drugie podejście wywołuje operand + Vector3
klasy, który ma podpis:
public static Vector3 operator +(Vector3 a, Vector3 b);
więc nie ma innego sposobu na osiągnięcie tego niż konwersja pos2d w Vector3 dzięki ukrytej obsadzie ukrytej, która nie może mieć innej formy.
Mam nadzieję na pomoc !!
Edytować
W Unity 5.0.1f1 Personal
z MonoDevelop-Unit 4.0.1
, jak mówi Alex M., linie:
transform.position = pos3d;
transform.position += pos2d;
wciąż rzucam błąd "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)'"
tak naprawdę + = używa obu podpisów
public static Vector3 operator +(Vector3 a, Vector3 b);
public static Vector2 operator +(Vector2 a, Vector2 b);
bez względu na to, że już wiem „gdzie” wynik powinien zostać umieszczony (chyba dlatego, że wypisanie Vector2 jest możliwe do rzucenia do miejsca docelowego (Vector3) i jeśli prawdopodobnie nie byłoby to możliwe, kompilator wybrałby ten z właściwym Typ wyjścia).
Dzięki za punkt Alex M.