Чому в 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.