ให้เวกเตอร์สองตัวต่อไปนี้:
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
ทำไมนี้
คำตอบ:
ข้อความปัญหาเต็ม:
ข้อผิดพลาด CS0121: การโทรไม่ชัดเจนระหว่างวิธีการต่อไปนี้หรือคุณสมบัติ:
UnityEngine.Vector2.operator +(UnityEngine.Vector2, UnityEngine.Vector2)' and
UnityEngine.Vector3.operator + (UnityEngine.Vector3, UnityEngine.Vector3) '
ความสามัคคีจัดเตรียมวิธีในการแปลงVector3
a 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
ได้รับการประเมินครั้งแรกก่อนที่จะพิจารณา "โดยที่ผลลัพธ์จะถูกนำไปใช้" ดังนั้นคอมไพเลอร์ไม่ทราบว่าจะใช้ cast ใด - เช่น coder - เพื่อให้มันทำงานได้
หากคุณต้องการเลื่อนไปสู่ 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/en-us/library/sa7629ew.aspx
นอกจากนี้ยังกล่าวว่า "ตัวดำเนินการ + = ไม่สามารถโหลดมากเกินไปโดยตรง แต่ประเภทที่ผู้ใช้กำหนดสามารถโอเวอร์โหลดตัวดำเนินการ + (ดูโอเปอเรเตอร์)" ดังนั้นเราควรจะคิดว่าVector3
's +=
ผู้ประกอบการทำหน้าที่ตามที่อธิบายไว้โดยไมโครซอฟท์ที่จะกล่าวว่า:
x += y
เทียบเท่ากับ
x = x + y
ยกเว้นว่า x ถูกประเมินเพียงครั้งเดียว ความหมายของตัวดำเนินการ + ขึ้นอยู่กับประเภทของ x และ y (นอกจากนี้สำหรับตัวถูกดำเนินการตัวเลขการต่อข้อมูลสำหรับตัวถูกดำเนินการสตริงและอื่น ๆ )
ดังนั้นเราจึงมั่นใจได้ว่าวิธีที่สองจะเรียกใช้ + operand ของVector3
คลาสซึ่งมีลายเซ็นต์:
public static Vector3 operator +(Vector3 a, Vector3 b);
ดังนั้นจึงไม่มีวิธีอื่นใดที่จะบรรลุเป้าหมายนี้ได้มากกว่าการแปลง pos2d ไปเป็น Vector3 ต้องขอบคุณนักแสดงที่ซ่อนเร้นซึ่งไม่สามารถอยู่ในรูปแบบอื่นใดได้
หวังว่าจะช่วย !!
แก้ไข
ในUnity 5.0.1f1 Personal
ด้วยMonoDevelop-Unit 4.0.1
ขณะที่อเล็กซ์เอ็มกล่าวว่าเส้น:
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
- ไม่สามารถดูได้อย่างชัดเจนว่านั่นคือสิ่งที่คุณมีความหมาย