I have a visual Element that I’m trying to get the correct screen space position for. I’ve tried several “positions” and none are correct unless the Scale Mode in the UI Panel Settings is Constant Pixel Size.
I have done a test where I am doing a ray to the mouse position which is 100% accurate. (See code and screenshot).
We noticed this was a limitation and added the missing API to achieve what you’re aiming for. The new API is Panel.scaledPixelsPerPoint and is only available in Unity 6. Here’s a usage example:
using UnityEngine;
using UnityEngine.UIElements;
[RequireComponent(typeof(UIDocument))]
public class UISpriteSync : MonoBehaviour
{
UIDocument uiDocument;
PanelSettings panelSettings;
IPanel uiPanel;
VisualElement targetVE;
public GameObject targetObject;
public float factor;
private void OnEnable()
{
uiDocument = GetComponent<UIDocument>();
uiPanel = uiDocument.rootVisualElement.panel;
panelSettings = uiDocument.panelSettings;
targetVE = uiDocument.rootVisualElement.Q<VisualElement>("unity-dragger");
targetVE.RegisterCallback<GeometryChangedEvent>(GeometryChange);
}
void GeometryChange(GeometryChangedEvent evt)
{
if (targetVE == null)
{
Debug.Log("targetVE is null");
return;
}
if (targetObject == null)
{
Debug.Log("targetObject is null");
return;
}
targetObject.transform.position = targetVE.LocalToWorld(targetVE.localBound).position * factor;
}
private void LateUpdate()
{
if (targetVE == null)
{
Debug.Log("targetVE is null");
return;
}
if (targetObject == null)
{
Debug.Log("targetObject is null");
return;
}
var localBounds = targetVE.contentRect.center;
var worldBounds = targetVE.LocalToWorld(localBounds);
var position = worldBounds;
var ppp = uiPanel.scaledPixelsPerPoint;
var factored = position * factor * ppp;
factored.y = Screen.height - factored.y;
factored = Camera.main.ScreenToWorldPoint(new Vector3(factored.x, factored.y, 10));
targetObject.transform.position = factored;
}
}