Unityで、Vector2とVector3を追加することは曖昧ですが、割り当てが曖昧なのはなぜですか?


11

次の2つのベクトルがあるとします。

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

この行があいまいです:

v3 += v2; // Unity reports dimension ambiguity

この割り当てはそうではありませんが:

v3 = v2; // Unity assigns despite different dimensions

どうしてこれなの?


それでは、AnkoとXavi Monteroのすばらしい回答に感謝します。問題を再現しようとすると、質問を変更する必要があることに気付きました。Vector2をtransform.positionに割り当てて、transform.position = a + b;になるようにすると、このことが起こります。ここで、aとbの両方がVector2であり、正しくコンパイルされ、xとyが割り当てられます。代わりに、行をtransform.position + = a;に変更しても機能しません。//またはb Unity 5.0.0fを使用していて、スクリプトはUI要素(画像)に添付されていますが、コンパイラには影響しませんが、シナリオを再現するための重要な情報になる場合があります。
SteakOverflow 2015

だから何をすべきか教えてくれます。それに応じて質問と回答を変更しますか、それとも新しい質問を開始しますか?
SteakOverflow 2015

Vector3 + Vector2およびVector3 + = Vector2は、どちらを暗黙的にもう一方に変換することもでき、実行する内容に応じて明示的にキャストする必要があるため、何を実行しても機能しません。あいまいさがないため、Vector3 = Vector2が機能します。変更したり、新しい質問を投稿したりする必要はないと思います。

ケースは私が説明したものとは少し異なるため、質問を変更すると言っています。
SteakOverflow 2015

いや、何も壊れません。

回答:


12

完全な問題メッセージ:

エラーCS0121:次のメソッドまたはプロパティ間の呼び出しがあいまいです:UnityEngine.Vector2.operator +(UnityEngine.Vector2, UnityEngine.Vector2)' andUnityEngine.Vector3.operator +(UnityEngine.Vector3、UnityEngine.Vector3) '

Unityは、暗黙的にa Vector3をaに、Vector2またはその逆に変換する方法を提供しました。+演算子は両方とも適用できるため、これによりケースが曖昧になります。

あなたのキャストVector2Vector3コンパイラが使用することを知っているように、その操作で明示的にUnityEngine.Vector3.operator +(UnityEngine.Vector3, UnityEngine.Vector3)

興味があれば、その特定のエラーに関するMicrosoftのドキュメントを参照してください


編集後に編集:

Vec3 += Vec2上記と同じ理由であいまいです。Vec3 += Vec2実際にいると想像してくださいVec3 = Vec3 + Vec2Vec3 + Vec2両方をもたらすことができるVector2Vector3により、あなたが望むものを指定する必要がありますなぜ暗黙の変換に答えとして。

Vec3 = Vec2Vec2は暗黙的にaに変換Vector3され、最初のVec3に割り当てられるため、あいまいではありません。そのため、Vector3 = Vector3Vec2をVector3手動でキャストする必要がないため、操作全体が本当に可能です。


Unityは、Vector3のxとyをVector2のxとyから割り当て、zを0fに設定することを想定しています。正しい?
SteakOverflow、2015

はい、Vec3 = Vec2がVec3 =(Vector3)Vec2と同等であると想像してください。その場合、実際にはそれ以外のものにすることはできないため、手動でキャストする必要はありません。

ええ、実際、私の質問には「Vector2を割り当てるときにVector3にキャストする必要がないのはなぜですか」のようなタイトルを付けることができます。完璧な質問のタイトルを付けたり、作成したりするのは私が一番ではありません:/アレックス、ありがとうございます。私の好奇心は満足しています。
SteakOverflow、2015

3

変数の名前を変更しましょう(わかりやすくするため):

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にはこれらのシグネチャは存在しないため、コンパイラはパラメータを既知のシグネチャに「キャスト」しようとします。

次に、コンパイラーはこれらの2つの潜在的なシグニチャーを見つけます。

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

したがって、2つの可能性があります。

したがって、両方のキャストが可能であるため、pos2dをVector3にキャストし、pos3dをVector2にキャストできます。コンパイラは、同じソースコードをコンパイルするための可能な方法を見つけます(自動非表示キャストが提供されている場合)。

pos3dをVector2にキャストして2番目の署名を続行するか、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に割り当てます(間違いありません)。

2行目は次と同等です。

transform.position = transform.position + pos2d;

特殊性については、transform.positionは1回しか評価されないため、+=演算子に関するこのMicrosoftページでわかるように、型が考慮されます。

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

さらに、「+ =演算子を直接オーバーロードすることはできませんが、ユーザー定義型は+演算子をオーバーロードできます(演算子を参照)。」したがって、Vector3+=演算子は、Microsoftの説明どおりに動作すると考える必要があります。

x += y

に相当

x = x + y

ただし、xは1回しか評価されません。+演算子の意味は、xおよびyのタイプ(数値オペランドの加算、文字列オペランドの連結など)によって異なります。

したがって、2番目のアプローチVector3は、シグネチャを持つクラスの+オペランドを確実に呼び出すことができます。

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

そのため、他の形式にすることはできない暗黙の隠しキャストのおかげで、pos2dをVector3に変換する以外にこれを達成する方法はありません。

お手伝いしたいです!!


編集

ではUnity 5.0.1f1 PersonalMonoDevelop-Unit 4.0.1、アレックスM.が言うように、行:

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)にキャスト可能であるため、そのキャストがおそらく不可能である場合、おそらくコンパイラは適切なものを選択します)出力タイプ)。

ポイントアレックスMをありがとう


+=どちらも機能しません、それはまだVector3+ Vector2です。私の答えをご覧ください。

正しい、あなたのものに賛成して、私のものを編集しなければならない。
Xavi Montero、

コメントを組み込むために編集しました。
Xavi Montero、

transform.position + = pos2dがコンパイル中です。私は明日より正確になります(バージョンのバグかもしれません)
SteakOverflow

編集後、シーケンスで失われました... so ... pos3d += pos2d(編集した質問に従って)失敗しますが、transform.position += pos2dコンパイル(上記のコメントに従って)?? そのままで.positionは奇妙に見えるでしょうVector3-それがあなたの意味していることかどうかはっきりとわかりません
Xavi Montero、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.