[Unity] UI follows 3D objects, world coordinates are converted to UI coordinates

1. Convert world coordinates to screen coordinates, and then convert UI coordinates

RectTransformUtility.ScreenPointToWorldPointInRectangle converts a screen-space point to a position in the RectTransform's local space on its rectangular plane.

The RectTransform parameter of ScreenPointToWorldPointInRectangle, preferably using the Canvas of this UI. The ui coordinate z-axis calculated in this way is relatively stable.

The cam parameter should be the camera associated with this screen point. For a RectTransform in a Canvas set to Screen Space - Overlay mode, the cam parameter should be null.

//此方法的摄像机用可以看到物体的摄像机。
Vector2 screenPos = Camera.main.WorldToScreenPoint(targetObj.transform.position); 
//此方法的摄像机用UI摄像机,。
RectTransformUtility.ScreenPointToWorldPointInRectangle(rt, screenPos, Camera.main,out Vector3 outPos);
rt.position = outPos;

Note: Since two calculations are performed based on the camera, the result calculated by this method will have a little deviation due to precision issues, resulting in ui jitter.

If it is written in Update or LateUpdate, it may move with the Camera and cause large jitters. Uninstalling FixedUpdate will jitter less. So I used the second method.

2. Convert the world coordinates to the screen coordinates, and calculate the screen coordinates as the localPosition of the UI

First, convert world coordinates to screen coordinates

//此方法的摄像机用可以看到物体的摄像机。
Vector2 screenPos = Camera.main.WorldToScreenPoint(targetObj.transform.position); 

The origin of the screen coordinates (0,0) is in the lower left corner, and the upper right corner is (Screen.width, Screen.heigth)

The origin (0,0) of the UI coordinates is at the exact center, so we need to subtract the offset (Screen.width / 2, Screen.heigth / 2).

Considering the hierarchical relationship of the UI, the localPosition of the parent object needs to be subtracted.

    	  screenPos.x -= Screen.width / 2;
            screenPos.y -= Screen.height / 2;
            while (rt.parent != null && rt.parent.GetComponent<Canvas>() == null)
            {
                screenPos -= rt.parent.localPosition;
                rt = rt.parent;
            }

Then assign the final coordinates to ui.

full code

	//此方法的摄像机用可以看到物体的摄像机。
	Vector2 screenPos = Camera.main.WorldToScreenPoint(targetObj.transform.position); 
    screenPos.x -= Screen.width / 2;
    screenPos.y -= Screen.height / 2;
	while (rt.parent != null && rt.parent.GetComponent<Canvas>() == null)
    {
            screenPos -= rt.parent.localPosition;
            rt = rt.parent;
    }
    rt.position = outPos;

This method will not cause UI jitter.

Guess you like

Origin blog.csdn.net/boyZhenGui/article/details/125913553