愚痴になります 最近Unityのエディタ拡張に取り組んでいます 難しいことはたくさんありますが、理解できないほどではありませんが、座標変換に関しては、それがわかりません。
これは調べてみないと分からないのですが、調べてみるとびっくりします Unityにはワールド座標、スクリーン座標、ローカル座標、ウィンドウ座標などたくさんの座標系があり、それぞれが異なります。 Unity Transformation の座標については非常に面倒ですが、エディタ モードで操作しない限り、実際には問題ありません。
問題は、エディターの拡張をしたいだけなので、ほとんど空白のフィールドに遭遇したことです。該当する記事がないわけではありません。エディター拡張の下に座標系変換に関する記事がありますが、私の場合はすべて間違っていました。混乱して直接関数を書いて実装したいと思ったこともありました。昼も夜も、私は偶然その問題を目にしました。
目次
問題を説明してください
2D ゲームを作っているのですが、編集モードで展開したウィンドウでデータのシーン座標を選択する必要があるのですが、最初に思いついたのはマウスの位置をワールド座標に変換することでした。いろいろな質問がありますが、ほとんどはBaiduで解決できるのですが、キーの座標変換に問題があり、欲しいデータが取得できません。
問題は~にあります
(ランダムで見つけた写真)
P1: 変換する必要がある P2 オブジェクト内の座標位置、つまりマウス クリックの位置
P2: オブジェクトの位置点
P3: シーンウィンドウの左上隅の位置
P4: シーンウィンドウの左下隅の位置
P1の座標を取得するコードは次のとおりです。
private void OnSceneView(SceneView sceneView)
{
//鼠标左键点击判断
if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
{
Vector2 newPosition;
//P2指P1所需要转换的位置的父物体
Transform P2 = GameObject.Find("P2").transform;
//坐标转换
RectTransformUtility.ScreenPointToLocalPointInRectangle(P2.GetComponent<RectTransform>(), GetMousePos(), sceneView.camera, out newPosition);
Debug.Log(newPosition);
}
}
}
編集モードではInputクラスが使えないのでシーンイベントクラスを利用します RectTransformUtility.ScreenPointToLocalPointInRectangleメソッドについては詳しく紹介しません 簡単に言うと画面座標をオブジェクト内の座標に変換するものです とても人情的で、しかし、それは違います。それを感じているときにそれを使用するのは少し拷問です。RectTransformUtility クラスには他の変換メソッドがあり、Baidu にかなりの数の回答があります。
最初はマウス位置を取得するために Event.current.mousePosition を使用していましたが、P1 を画面座標からワールド座標に変換したくて、Camera 付属の変換関数を使用しましたが、これが間違いでした。P1 の座標は正しいデータではなく、正確な画面座標ではないためです。
一般的に使用される座標系には次のものがあります。
P1 の座標は GUI 座標系にあるため、直接変換できません。Event.current.mousePosition で取得されるマウス座標は GUI 座標であるため、使用する前に Screen 座標系に変換する必要があります。
つまり、P3 が GUI 座標系の原点、P4 がスクリーン座標系の原点となり、P1 は P3 の座標系、P2 はワールド座標系になります。この乱雑な座標系で実行されます。
解決
public static Vector3 GetMousePos()
{
SceneView sceneView = SceneView.currentDrawingSceneView;
//当前屏幕坐标,左上角(0,0)右下角(camera.pixelWidth,camera.pixelHeight)
Vector2 mousePos = Event.current.mousePosition;
//retina 屏幕需要拉伸值
float mult = 1;
#if UNITY_5_4_OR_NEWER
mult = EditorGUIUtility.pixelsPerPoint;
#endif
//转换成摄像机可接受的屏幕坐标,左下角是(0,0,0);右上角是
(camera.pixelWidth,camera.pixelHeight,0)
mousePos.y = sceneView.camera.pixelHeight - mousePos.y * mult;
mousePos.x *= mult;
//近平面往里一些,才能看到摄像机里的位置
Vector3 fakePoint = mousePos;
fakePoint.z = 10;
return fakePoint;
}
この関数が返すのは、GUI 座標系の座標をスクリーン座標系に変換した、正確なスクリーン座標です。インターネットからコードを直接取得して変更しました。2D プロジェクトなので、スクリーン座標系とは何の関係もありません。 Z 軸についてはカメラの背面に設定されているため、説明しません。
上記コードのソース: Unity は、シーンの下のマウス位置の世界座標を取得します window_BRK Xiaobu のブログ - CSDN blog_unity はウィンドウの位置を取得します
ソースコードを直接ワールド座標に変換することも可能ですが、場合によってはカメラの変換機能を利用することも可能だと思いますが、ソースコードをオブジェクト内の座標系に変換することはできません。
要約する
Unity のクソ、座標変換は人を殺しますが、この内容を一度理解すれば、基本的には今後同様の問題に遭遇する可能性があります。
取得した座標がどの座標系にあるのかを把握し、対応する座標系に変換します。ちなみに、原因の 1 つは、間違ったカメラを使用したためです。プロジェクトには 2 つのカメラがありますが、両方とも間違っています。これは実際には落とし穴であるはずですが、まだ理解していません。これをテストするのに長い時間がかかりました。それをテストした後、正しいデータを取得するために最終的に sceneView.camera に変更しました。隠しカメラはありますか? よくわかりません。OnSceneView (SceneView sceneView) イベント関数を使用する場合は、 sceneView.camera カメラを直接実行します。はい、おそらく (⊙_⊙)。
最後に、私があなたのお役に立てれば、この記事を書く目的はおそらく達成できたと思います。