Gegenseitige Konvertierung von Transformation, Recttransform und Position der Unity-Benutzeroberfläche

Ich bin in der Studie auf einige Fallstricke gestoßen und habe sie aufgezeichnet, da die Koordinatentransformation von RectTransform zum ersten Mal auf echte Kopfschmerzen gestoßen ist

1. Zunächst müssen wir verstehen, dass RectTransform eine Unterklasse von Transform ist und dass für alle UI-Komponenten die im Code erhaltene transform.position tatsächlich rectTransform.anchoredPosition ist, dh ein neues leeres Objekt erstellen und ein Bild hinzufügen , Text und andere Komponenten: Dieses Objekt kann nur unter Canvas angezeigt werden und seine Transform-Komponente wird automatisch durch RectTransform ersetzt.

2. rectTransform.anchoredPosition sind die Koordinaten des Drehpunkts des UI-Objekts, der seinem Ankerpunkt entspricht. Wenn der Ankerpunkt ein Punkt ist, ist es einfacher zu verstehen. Wenn der Ankerpunkt die vier Ecken des Bedienfelds oder der Leinwand des übergeordneten Objekts sind Es beinhaltet auch die Einheit. Einige interne Berechnungen werden hier nicht näher untersucht.

3. Was sollen wir also tun, wenn wir die Weltkoordinaten jeder Benutzeroberfläche benötigen, um einige Vorgänge auszuführen?

Annahmen: (1) Die Ziel-UI befindet sich unter der Leinwand, der Modus der Leinwand ist Kamera und die Kamera ist eine spezielle UI-Kamera. Zu diesem Zeitpunkt sind die Benutzeroberfläche und die Leinwand in der Szene als Teil des Spielobjekts sichtbar.

(2) Wir haben auch eine Hauptkamera, um die gesamte Spielszene aufzunehmen und zu rendern

(3) Wir benötigen einen Linerenderer, der von der Benutzeroberfläche aus auf ein Objekt in der Szene zeigt.

Dann sind die Koordinaten der Objekte in der Szene leicht zu ermitteln. Was wir benötigen, sind die Koordinaten der Benutzeroberfläche.

Schritt 1: Konvertieren Sie die Position der Benutzeroberfläche in Bildschirmkoordinaten

Unity stellt eine Methode RectTransformUtility.WorldToScreenPoint(Camera camera, Vector3 point) bereit. Wir übergeben die transform.position der Benutzeroberfläche, die die tatsächliche rectTransform.anchoredPosition ist, an den Punkt und übergeben die UIcamera an die Kamera, um den Bildschirm der Benutzeroberfläche zu erhalten Koordinate.

RectTransformUtility.WorldToScreenPoint(UIcamera,transform.position)

Der zweite Schritt besteht darin, die Bildschirmkoordinaten in Weltkoordinaten umzuwandeln

这时我们所选用的摄像机就由UIcamera换成Camera.main,因为canvas在任何位置都不影响UIcamera渲染它,而我们游戏世界是由maincamera来渲染的,所以此时摄像机应该使用mainCamera。

unity同样提供了一个方法Camera.ScreenToWorldPoint(Vector3 point)来处理这个问题,需要注意的是,之前RectTransformUtility.WorldToScreenPoint方法的返回值是一个Vector2,而这个方法的入参是vector3,需要处理一下Z轴,否则返回值永远是一个(0,0,0)的三维向量。

 //主相机到2D界面的距离
            float distance = Mathf.Abs(GameObject.Find("BackGroundCanvas").GetComponent<Canvas>().planeDistance) ;
            // return GameObject.Find("UICamera").GetComponent<Camera>().ScreenToWorldPoint(new Vector3(mousPos.x, mousPos.y, distance));
            return camera.ScreenToWorldPoint(new Vector3(mousPos.x, mousPos.y, distance));

此处我的项目是一个2D项目,暂时的Z轴使用背景层canvas的planedistance,方法外部再进行-1,以保证生成的linerenderer在背景层上显示。

第二个坑: UI预制体创建时如果没有指定父物体为canvas,就会导致位置、大小出现问题

因为canvas的camera模式在渲染时是进行了缩放的:如果没有缩放,那么比如canvas的planedistance设定为100,那么在摄像机中看到的canvas就会非常小了。如果没有指定父物体为canvas或其子物体,就会导致创建出来的UI物体巨大,位置也因为LocalPosition等变换问题出现奇怪的偏移

总结:折腾了一天才处理明白,我的处理方法应该也不是最好的,因为感觉堆2D项目中Z轴、DEPTH的理解还不够清晰。

Guess you like

Origin blog.csdn.net/NerfmePlz/article/details/128938577