Trong Unity, tại sao việc thêm Vector2 và Vector3 lại mơ hồ nhưng việc gán không phải là?


11

Cho hai vectơ sau:

Vector3 v3 = Vector3.one;
Vector2 v2 = Vector2.one;

Dòng này không rõ ràng:

v3 += v2; // Unity reports dimension ambiguity

Trong khi nhiệm vụ này không phải là:

v3 = v2; // Unity assigns despite different dimensions

Tại sao lại thế này?


Vì vậy, cảm ơn bạn rất nhiều đến Anko và Xavi Montero vì những câu trả lời tuyệt vời. Cố gắng tái tạo vấn đề tôi nhận ra câu hỏi của mình nên được thay đổi. Thực tế đang xảy ra khi gán Vector2 cho biến đổi.poseition sao cho biến đổi.poseition = a + b; trong đó CẢ HAI và b là Vector2 biên dịch chính xác và nó gán x và y! Thay vào đó, nó không hoạt động khi tôi thay đổi dòng thành biến đổi.poseition + = a; // hoặc b Tôi đang sử dụng Unity 5.0.0f và tập lệnh được đính kèm với thành phần UI (Hình ảnh) không ảnh hưởng đến trình biên dịch nhưng có thể là thông tin quan trọng để bạn tái tạo kịch bản.
SteakOverflow

Vì vậy, các bạn cho tôi biết phải làm gì. Chúng ta sẽ thay đổi câu hỏi và câu trả lời của bạn cho phù hợp hay chúng ta sẽ bắt đầu một câu hỏi mới?
SteakOverflow

Vector3 + Vector2 và Vector3 + = Vector2 sẽ không bao giờ hoạt động cho dù bạn muốn gì vì cả hai có thể được chuyển đổi hoàn toàn sang cái khác và bạn cần phải phân biệt rõ ràng theo những gì bạn muốn làm. Vector3 = Vector2 hoạt động vì không có sự mơ hồ. Tôi không thấy cần phải thay đổi hoặc đăng câu hỏi mới.

Tôi đang nói để thay đổi câu hỏi vì trường hợp hơi khác so với những gì tôi mô tả, điều này có thể ngăn chặn dòng câu trả lời của bạn.
SteakOverflow

Không lo lắng, không có gì phá vỡ.

Câu trả lời:


12

Thông báo vấn đề đầy đủ:

lỗi CS0121: Cuộc gọi không rõ ràng giữa các phương thức hoặc thuộc tính sau: UnityEngine.Vector2.operator +(UnityEngine.Vector2, UnityEngine.Vector2)' andUnityEngine.Vector3.operator + (UnityEngine.Vector3, UnityEngine.Vector3) '

Unity cung cấp một cách để ngầm chuyển đổi a Vector3thành a Vector2và ngược lại. Điều này gây ra sự mơ hồ trong trường hợp của bạn vì cả hai toán tử + đều có thể được áp dụng.

Truyền của bạn Vector2một Vector3cách rõ ràng trong hoạt động đó, để trình biên dịch biết sử dụng UnityEngine.Vector3.operator +(UnityEngine.Vector3, UnityEngine.Vector3).

Nếu bạn tò mò, tài liệu của Microsoft về lỗi cụ thể đó có ở đây .


Chỉnh sửa sau khi chỉnh sửa của bạn:

Vec3 += Vec2là mơ hồ cho cùng một lý do được mô tả ở trên. Hãy tưởng tượng Vec3 += Vec2trong thực tế Vec3 = Vec3 + Vec2. Vec3 + Vec2có thể mang lại cả hai Vector2Vector3như câu trả lời do chuyển đổi ngầm định, đó là lý do tại sao bạn phải chỉ định những gì bạn muốn.

Vec3 = Vec2không mơ hồ vì Vec2 được chuyển đổi hoàn toàn thành a Vector3và sau đó được gán cho Vec3 ban đầu. Vì vậy, toàn bộ hoạt động thực sự Vector3 = Vector3không có bạn phải chuyển Vec2 sang Vector3thủ công.


Vì vậy, Unity giả định rằng tôi muốn x và y của Vector3 được gán từ x và y của Vector2 và z của tôi được đặt thành 0f. Đúng?
SteakOverflow

Đúng, hãy tưởng tượng Vec3 = Vec2 tương đương với Vec3 = (Vector3) Vec2. Bạn không cần phải chọn thủ công vì nó thực sự không thể là gì khác ngoài trường hợp đó.

Vâng, thực sự câu hỏi của tôi có thể có tiêu đề đại loại như "Tại sao tôi không cần truyền cho Vector3 khi gán Vector2". Tôi không phải là người giỏi nhất trong việc chuẩn bị và tạo ra những câu hỏi hoàn hảo: / Cảm ơn Alex. Sự tò mò của tôi đã được (hơn) hài lòng.
SteakOverflow

3

Hãy để tôi đổi tên các vars (cho rõ ràng):

Vector3 pos3d = new Vector3 (1f, 2f, 3f);
Vector2 pos2d = new Vector2 (1f, 2f);

Câu trả lời

Đó là vì phần pos3d + pos2dcủa dòng. Phần này thực sự mơ hồ trong khi phần +=này thì không. Hãy để tôi làm rõ tại sao một và tại sao khác.

Phân tích 1

Trong dòng này

transform.position = pos3d + pos2d;

đầu tiên trình biên dịch sẽ cố gắng đánh giá biểu thức pos3d + pos2dtrước khi tiếp tục, bất kể kết quả sẽ được đặt ở đâu.

Để làm như vậy, trước tiên hệ thống sẽ cố gắng tìm bất kỳ hàm tĩnh công khai nào có thêm Vector3 cộng với Vector2, ví dụ chữ ký có thể này:

public static Vector3 operator +(Vector3 a, Vector2 b);

hoặc ví dụ chữ ký có thể này:

public static Vector2 operator +(Vector3 a, Vector2 b);

Tuy nhiên, không có bất kỳ chữ ký nào trong API để trình biên dịch cố gắng "truyền" các tham số thành các chữ ký đã biết.

Sau đó, trình biên dịch tìm thấy hai chữ ký tiềm năng đó:

public static Vector3 operator +(Vector3 a, Vector3 b);
public static Vector2 operator +(Vector2 a, Vector2 b);

Những tài liệu này được ghi lại ở đây: http://docs.unity3d.com/ScriptReference/Vector3-operator_add.html và tại đây: http://docs.unity3d.com/ScriptReference/Vector2-operator_add.html

Vì vậy, có hai khả năng:

Vì vậy, vì cả hai vật đúc đều có thể, pos2d có thể được đúc thành Vector3 và pos3d được castabale thành Vector2, trình biên dịch sau đó tìm ra các cách có thể để biên dịch cùng mã nguồn (được cung cấp các phôi ẩn tự động).

Có thể truyền pos3d vào Vector2 và tiếp tục với chữ ký thứ hai hoặc chuyển pos2d vào Vector3 và tiếp tục với chữ ký đầu tiên.

Vì biểu thức pos3d + pos2dđược đánh giá đầu tiên, trước khi xem xét "nơi kết quả sẽ được áp dụng", trình biên dịch không biết bạn sẽ sử dụng bộ mã hóa nào - như trình mã hóa để thực hiện.

Nếu bạn muốn chuyển sang 3D, bạn có thể viết điều này:

transform.position = pos3d + ( Vector3 )pos2d;

và vấn đề không còn nữa, vì bây giờ thì rõ ràng: đầu tiên di chuyển pos2d sang một đối tượng khác thuộc loại Vector3, sau đó thực hiện tổng của Vector3 + Vector3. Với điều kiện là có chữ ký tĩnh này

public static Vector3 operator +(Vector3 a, Vector3 b);

có sẵn, cái đó sẽ được sử dụng mà không có sự mơ hồ nào cả.

Phân tích 2

Mặt khác, khi bạn làm

transform.position = pos3d;
transform.position += pos2d; 

không có sự mơ hồ: Dòng đầu tiên gán Vector3 thành Vector3 (không có nghi ngờ).

Dòng thứ hai tương đương với

transform.position = transform.position + pos2d;

với tính đặc biệt, Transform.poseition chỉ được đánh giá một lần và do đó loại được xem xét, như bạn có thể thấy trong trang Microsoft này về +=toán tử:

https://msdn.microsoft.com/en-us/l Library / sa7629ew.aspx

Ngoài ra, nó nói "Toán tử + = không thể bị quá tải trực tiếp, nhưng các kiểu do người dùng định nghĩa có thể quá tải toán tử + (xem toán tử)." vì vậy chúng ta nên nghĩ toán tử Vector3của +=toán tử hoạt động như được mô tả bởi microsoft nơi nó nói:

x += y

tương đương với

x = x + y

ngoại trừ x chỉ được đánh giá một lần. Ý nghĩa của toán tử + phụ thuộc vào loại x và y (bổ sung cho toán hạng số, nối cho toán hạng chuỗi, v.v.).

vì vậy chúng ta có thể chắc chắn cách tiếp cận thứ hai gọi + toán hạng của Vector3lớp, có chữ ký:

public static Vector3 operator +(Vector3 a, Vector3 b);

Vì vậy, không có cách nào khác để đạt được điều này ngoài việc chuyển pos2d thành Vector3 nhờ vào một diễn viên ẩn ẩn không thể ở bất kỳ dạng nào khác.

Mong được giúp đỡ !!


Biên tập

Trong Unity 5.0.1f1 Personalvới MonoDevelop-Unit 4.0.1, như Alex M. cho biết, các đường:

transform.position = pos3d;
transform.position += pos2d;

vẫn báo lỗi "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)'"

Vì vậy, thực sự + = đang sử dụng cả hai chữ ký

public static Vector3 operator +(Vector3 a, Vector3 b);
public static Vector2 operator +(Vector2 a, Vector2 b);

bất kể thực tế là đã biết "kết quả" sẽ được đặt ở đâu (tôi đoán bởi vì việc xuất ra Vector2 có thể được chuyển đến đích (Vector3) và nếu có thể, thì trình biên dịch sẽ chọn một kết quả phù hợp Loại đầu ra).

Cảm ơn vì điểm Alex M.


+=cũng không hoạt động, nó vẫn là Vector3+ Vector2. Xem câu trả lời của tôi.

Phải, nâng cấp của bạn, sẽ chỉnh sửa của tôi.
Xavi Montero

Chỉ cần chỉnh sửa để kết hợp nhận xét của bạn.
Xavi Montero

biến đổi.poseition + = pos2d đang biên dịch. Tôi sẽ chính xác hơn vào ngày mai (có thể chỉ là một lỗi phiên bản)
SteakOverflow

Sau khi chỉnh sửa, tôi bị lạc trong trình tự ... vì vậy ... pos3d += pos2d(theo câu hỏi đã chỉnh sửa của bạn) không thành công nhưng transform.position += pos2dbiên dịch (theo nhận xét của bạn ở trên) ?? Sẽ có vẻ kỳ lạ như .positionVector3- Không thể thấy rõ nếu đó là những gì bạn có nghĩa.
Xavi Montero
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.