Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Convert world position to UI for UIToolkit's UI element?

Discussion in 'UI Toolkit' started by Spikebor, Jul 2, 2023.

  1. Spikebor

    Spikebor

    Joined:
    May 30, 2019
    Posts:
    269
    Say I have a character and I know its head transform world position.
    How to display a UI on top of it head?
    I have a VisualElement named targetUI which position has set to Absolute.
    Code (CSharp):
    1.                 Vector2 screenPoint = Camera.main.WorldToScreenPoint(headWorldPosition);
    2.                 targetUI.style.right = screenPoint.x;
    3.                 targetUI.style.bottom = screenPoint.y;
    This didn't work.
     
  2. Spikebor

    Spikebor

    Joined:
    May 30, 2019
    Posts:
    269
    Code (CSharp):
    1.                 Vector2 screenPoint = Camera.main.WorldToScreenPoint(worldPosition);
    2.                 target.style.top = Screen.height - screenPoint.y;
    3.                 target.style.left = screenPoint.x;
    This code does work, but only work for my design time resolution (960x540)
    as soon as I switch the resolution to different, say 1920x1080, this code no longer works.
    Please help, I don't understand...
     
  3. Maverick

    Maverick

    Joined:
    Dec 18, 2009
    Posts:
    224
  4. Spikebor

    Spikebor

    Joined:
    May 30, 2019
    Posts:
    269
    Thank you, I changed the code to this

    Code (CSharp):
    1.                
    2.                Vector2 screenPoint = Camera.main.WorldToScreenPoint(worldPosition);
    3.                 var panelPos= RuntimePanelUtils.ScreenToPanel(target.panel, screenPoint);
    4.                 target.style.top = Screen.height - panelPos.y;
    5.                 target.style.left = panelPos.x;
    6.  
    It results in the same situation, it works with my design time resolution, but not with other resolutions.
     
  5. Maverick

    Maverick

    Joined:
    Dec 18, 2009
    Posts:
    224
    Here is my try:
    Code (CSharp):
    1.  
    2. var screenPosition = Camera.main.WorldToScreenPoint(target.transform.position);
    3. screenPosition.y = Screen.height - screenPosition.y;
    4. var panelLocalPosition = RuntimePanelUtils.ScreenToPanel(uiDocument.rootVisualElement.panel, screenPosition);
    5. //var panelLocalPosition = RuntimePanelUtils.CameraTransformWorldToPanel(uiDocument.rootVisualElement.panel, target.transform.position, Camera.main);
    6. _ve.style.top = panelLocalPosition.y;
    7. _ve.style.left = panelLocalPosition.x;
    8.  
     
  6. martinpa_unity

    martinpa_unity

    Unity Technologies

    Joined:
    Oct 18, 2017
    Posts:
    354
    I believe you should be able to use
    RuntimePanelUtils.CameraTransformWorldToPanel(uiDocument.rootVisualElement.panel, target.transform.position + new Vector3( /* offset from transform */ ), Camera.main);
    in this case.

    If possible, I would look into using the
    style.translate
    property instead of using
    style.top
    and
    style.left
    , as the translate property won't require to recompute the layout on a change and should be more efficient.