Чому в Unity чому додавання Vector2 та Vector3 неоднозначно, але призначення не є?


11

З огляду на наступні два вектори:

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

Цей рядок неоднозначний:

v3 += v2; // Unity reports dimension ambiguity

хоча це завдання не:

v3 = v2; // Unity assigns despite different dimensions

Чому це?


Тож дуже дякую Анко та Хаві Монтеро за чудові відповіді. Намагаючись відтворити проблему, я зрозумів, що моє питання слід змінити. Факт відбувається при призначенні вектора2 трансформації.позиція таким чином, що трансформація.позиція = a + b; де BOTH a і b - Vector2 компілюється правильно, і він призначає x і y! Натомість він не працює, коли я змінюю рядок на transform.position + = a; // або b Я використовую Unity 5.0.0f, і сценарій додається до елемента інтерфейсу (Зображення), який не впливає на компілятор, але може бути важливою інформацією для відтворення сценарію.
SteakOverflow

Тож ви, хлопці, скажіть, що мені робити. Чи відповідно змінимо питання і ваші відповіді чи розпочнемо нове?
SteakOverflow

Vector3 + Vector2 та Vector3 + = Vector2 ніколи не працюватиме незалежно від того, що ви хочете, тому що обидва можна неявно перетворити на інший, і вам потрібно чітко вказати те, що ви хочете зробити. Vector3 = Vector2 працює, тому що двозначності немає. Я не бачу необхідності змінювати або публікувати нове запитання.

Я хочу змінити питання, оскільки справа трохи відрізняється від описаного мною, що може гальмувати потік вашої відповіді.
SteakOverflow

Ні, не хвилюйся, нічого не ламається.

Відповіді:


12

Повне повідомлення про випуск:

помилка CS0121: виклик неоднозначний між такими методами чи властивостями: UnityEngine.Vector2.operator +(UnityEngine.Vector2, UnityEngine.Vector2)' andUnityEngine.Vector3.operator + (UnityEngine.Vector3, UnityEngine.Vector3) '

Єдність запропонувала спосіб неявного перетворення a Vector3в a Vector2і навпаки. Це спричиняє неоднозначність у вашому випадку, оскільки можна застосувати обидва + оператора.

Віддайте свій Vector2до Vector3явно в цій операції, так що компілятор знає використовувати UnityEngine.Vector3.operator +(UnityEngine.Vector3, UnityEngine.Vector3).

Якщо вам цікаво, документи Microsoft, для цієї конкретної помилки є тут .


Редагувати після редагування:

Vec3 += Vec2неоднозначно з тієї ж причини, описаної вище. Уявіть, що ви Vec3 += Vec2є насправді Vec3 = Vec3 + Vec2. Vec3 + Vec2може давати як Vector2і Vector3як відповідь через неявні перетворення, тому вам потрібно вказати, що ви хочете.

Vec3 = Vec2не є неоднозначним, оскільки Vec2 неявно перетворюється на a, Vector3а потім присвоюється початковому Vec3. Таким чином, вся операція насправді Vector3 = Vector3не потребує передачі Vec2 Vector3вручну.


Таким чином, Unity передбачає, що я хочу, щоб мої Vector3 x і y були призначені з x і y мого Vector2, а мій z встановлений на 0f. Правильно?
SteakOverflow

Так, уявіть, що Vec3 = Vec2 еквівалентний Vec3 = (Vector3) Vec2. Не потрібно робити це вручну, оскільки в цьому випадку насправді не може бути нічого іншого, крім цього.

Так, насправді моє запитання може бути названо на кшталт "Чому мені не потрібно звертатися до Vector3 при призначенні Vector2". Я не найкращий у титулюванні та розробці ідеальних питань: / Дякую Алекс. Моя цікавість була (над) задоволена.
SteakOverflow

3

Дозвольте мені перейменувати значення vars (для наочності):

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

Відповідь

Це через переріз pos3d + pos2dрядка. Ця частина дійсно неоднозначна, а +=ні. Дозвольте мені уточнити, чому одне і чому інше.

Аналіз 1

У цьому рядку

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);

Доступний, той буде використовуватися зовсім не двозначно.

Аналіз 2

З іншого боку, коли ти робиш

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, що +=оператор оператора діє так, як описано в Microsoft, де він говорить:

x += y

еквівалентно

x = x + y

за винятком того, що х оцінюється лише один раз. Значення оператора + залежить від типів x і y (додавання для числових операндів, конкатенація для рядкових операндів тощо).

тож ми можемо бути впевнені, що другий підхід викликає + операнд 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), і якби цей виступ не був можливим, можливо, компілятор обрав би той, з відповідним тип виходу).

Дякую за бал Алекс М.


+=також не працює, це все ще Vector3+ Vector2. Дивіться мою відповідь.

Правильно, заохочуючи своє, слід редагувати моє.
Хаві Монтеро

Просто відредагований, щоб включити ваш коментар.
Хаві Монтеро

transform.position + = pos2d складається. Я буду точнішим завтра (можливо, це просто помилка версії)
SteakOverflow

Після редагувань я загубився в послідовності ... так що ... pos3d += pos2d(відповідно до Вашого відредагованого питання) не вдається, але transform.position += pos2dкомпілюється (відповідно до Вашого коментаря вище) ?? Здавалося б, дивно, як .positionце Vector3- Не можу чітко зрозуміти, чи це ти маєш на увазі.
Хаві Монтеро
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.