Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
17
Question by morbidcamel · Sep 29, 2014 at 07:49 AM · guiunity 4.6recttransform

How to convert from world space to canvas space?

I have a screen space canvas and I simply want to move a "target" over an object in world space. My world space coordinate is obtained with a raycast and I do a debug draw to make sure it is correct. The problem is none of the following code is giving me the right result.

 void Awake()
     {
         rt = (RectTransform)this.transform;
     }
 
     void Update()
     {
         if (currentSelection == null)
             return;
 
         // Translate world position to UI coordinates
         Vector3 pos =  ((RectTransform)rt.parent).InverseTransformPoint(currentSelection.position);
         rt.position = pos; // nether rt or rt.parent works!
 
     }
Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image morbidcamel · Oct 03, 2014 at 02:17 AM 0
Share

Seriously no answers out there?

15 Replies

· Add your reply
  • Sort: 
avatar image
49

Answer by Sylos · Nov 24, 2014 at 02:32 PM

I solved this problem by doing the following:

 //this is your object that you want to have the UI element hovering over
 GameObject WorldObject;
 
 //this is the ui element
 RectTransform UI_Element;
 
 //first you need the RectTransform component of your canvas
 RectTransform CanvasRect=Canvas.GetComponent<RectTransform>();
 
 //then you calculate the position of the UI element
 //0,0 for the canvas is at the center of the screen, whereas WorldToViewPortPoint treats the lower left corner as 0,0. Because of this, you need to subtract the height / width of the canvas * 0.5 to get the correct position.
 
 Vector2 ViewportPosition=Cam.WorldToViewportPoint(WorldObject.transform.position);
 Vector2 WorldObject_ScreenPosition=new Vector2(
 ((ViewportPosition.x*CanvasRect.sizeDelta.x)-(CanvasRect.sizeDelta.x*0.5f)),
 ((ViewportPosition.y*CanvasRect.sizeDelta.y)-(CanvasRect.sizeDelta.y*0.5f)));
 
 //now you can set the position of the ui element
 UI_Element.anchoredPosition=WorldObject_ScreenPosition;

Comment
Add comment · Show 10 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ian_sorbello · Mar 23, 2015 at 01:55 AM 1
Share

This solution works well - AND is very performant.

avatar image Vahradrim ian_sorbello · Apr 17, 2017 at 02:46 PM 2
Share

No it's not really performant, and it's not correct. Here is the right code I made :

 using UnityEngine;
 
 /// <summary>
 /// Place an UI element to a world position
 /// </summary>
 [RequireComponent(typeof(RectTransform))]
 public class PlaceUIElementAtWorldPosition : $$anonymous$$onoBehaviour
 {
     private RectTransform rectTransform;
     private Vector2 uiOffset;
     
     /// <summary>
     /// Initiate
     /// </summary>
     void Start ()
     {
         // Get the rect transform
         this.rectTransform = GetComponent<RectTransform>();
 
         // Calculate the screen offset
         this.uiOffset = new Vector2((float)Canvas.sizeDelta.x / 2f, (float)Canvas.sizeDelta.y / 2f);
     }
 
     /// <summary>
     /// $$anonymous$$ove the UI element to the world position
     /// </summary>
     /// <param name="objectTransformPosition"></param>
     public void $$anonymous$$oveToClickPoint(Vector3 objectTransformPosition)
     {
         // Get the position on the canvas
         Vector2 ViewportPosition = Camera.main.WorldToViewportPoint(objectTransformPosition);
         Vector2 proportionalPosition = new Vector2(ViewportPosition.x * Canvas.sizeDelta.x, ViewportPosition.y * Canvas.sizeDelta.y);
         
         // Set the position and remove the screen offset
         this.rectTransform.localPosition = proportionalPosition - uiOffset;
     }
 }
 
avatar image michaelday008 Vahradrim · Jun 19, 2019 at 12:45 AM 0
Share

Thanks for this! I was struggling with the problem of how to get $$anonymous$$imap indicators to render in screen space on the $$anonymous$$imap and this worked wonders.

I needed to take 2 things into consideration for my implementation though: 1. If your canvas has a content size fitter, make sure it is set to unconstrained or it may be zero size, causing your icons to render too far up and left. 2. The actual image or text you are trying to render should be a child of the canvas so you can move it relative to the canvas. If you try to move the canvas, the screen space camera mode will just re-center it on the next update.

Show more comments
avatar image RawSpartano · Apr 25, 2015 at 01:00 PM 0
Share

for me Canvas.GetComponent doesnt work. it says : A field initializer cannot reference the nonstatic field, method, or property `UnityEngine.Component.GetComponent(System.Type)'

avatar image Almamu · May 05, 2015 at 08:14 PM 1
Share

$$anonymous$$y two cents: Take in $$anonymous$$d that you might need to change the calculations based on the anchor of the gui element you are drawing, i'm used to work with top-left anchors, so this wasn't correct at all, ins$$anonymous$$d I used this:

         // get the initial position for the element
         Vector3 character = this.mGameController.Character.transform.position;
         Vector2 viewport = this.mGameController.Camera.WorldToViewportPoint (character);
         Vector2 screenPosition = new Vector2
         (
             viewport.x * this.mGameController.GUICanvasRect.sizeDelta.x,
             viewport.y * this.mGameController.GUICanvasRect.sizeDelta.y
         );
 
         // this is reversed because of the anchor we are using for this element
         screenPosition.y = -screenPosition.y;
avatar image Almamu · May 05, 2015 at 09:21 PM 0
Share

@RawSpartano Canvas is not a gameObject, take in $$anonymous$$d that GetComponent is only available for gameObjects not Canvas/RecTransform/etc types, so make sure you use a GameObject ins$$anonymous$$d of a Canvas

avatar image pbastia · Oct 14, 2016 at 04:47 PM 0
Share

Just wanted to add that using the sizeDelta only works if your anchors are all grouped together. Otherwise, sizeDelta is not equivalent to the component's size. Good answer though, I ended up going for your solution :)

Show more comments
avatar image
37

Answer by leni8ec · Dec 13, 2014 at 02:15 AM

This issue also has another solution:

 Vector2 pos = gameObject.transform.position;  // get the game object position
 Vector2 viewportPoint = Camera.main.WorldToViewportPoint(pos);  //convert game object position to VievportPoint
 
 // set MIN and MAX Anchor values(positions) to the same position (ViewportPoint)
 rectTransform.anchorMin = viewportPoint;  
 rectTransform.anchorMax = viewportPoint; 

 



Comment
Add comment · Show 11 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Poculis · Jan 07, 2015 at 09:46 AM 0
Share

This solution works great for me +1

avatar image Bankler · Mar 09, 2015 at 03:09 PM 1
Share

Thanks so much! Was spending hours to get this to work, and this solved it. (Small note on typo, ViewportPosition is called ViewportPoint on line 5 and 6).

avatar image TutiBueno2 · Mar 11, 2015 at 09:18 PM 0
Share
  • worked nicely.

avatar image leni8ec · Mar 12, 2015 at 09:41 AM 0
Share

Bankler, Thank you, I fix it.

avatar image Almamu · May 05, 2015 at 09:23 PM 2
Share

This is not as correct as @Sylos answer is, take in $$anonymous$$d that changing the anchor you limit the position where the gui element can move to BUT you don't actually move the element on the GUI canvas, thats why unity is so "slow" when changing these values.

Show more comments
avatar image
14

Answer by Stardog · Jan 10, 2015 at 09:05 AM

This is the cleanest way I can find of making a UI element follow a world object's 3D position.

 public RectTransform canvasRectT;
 public RectTransform healthBar;
 public Transform objectToFollow;

 void Update()
 {
     Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(Camera.main, objectToFollow.position);

     healthBar.anchoredPosition = screenPoint - canvasRectT.sizeDelta / 2f;
 }

Reading Sylos's answer above helped.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Cameron_SM · Feb 20, 2015 at 03:52 AM 0
Share

I don't see how RectTransformUtility.WorldToScreenPoint can ever do anything useful, it's static and you don't pass in a reference to a rect so it has no way of knowing what you mean, all it does the the exact same as Camera.main.WorldToScreenPoint (I've tested, several times) would which will work but only if you've got a specific non-scaled canvas setup.

avatar image Suhrahj · Dec 24, 2016 at 04:15 PM 1
Share

I mean... this works quite well for me, I don't see why I should deal with the chaos up there, is this low performance or sth?

avatar image
10

Answer by YoungDeveloper · Aug 20, 2015 at 04:49 PM

I wrote a static function which requires canvas rectransform, camera and vector position. That way you can work with multiple canvas and cameras. Works like a charm.

 private Vector2 WorldToCanvasPosition(RectTransform canvas, Camera camera, Vector3 position) {
         //Vector position (percentage from 0 to 1) considering camera size.
         //For example (0,0) is lower left, middle is (0.5,0.5)
         Vector2 temp = camera.WorldToViewportPoint(position);
 
         //Calculate position considering our percentage, using our canvas size
         //So if canvas size is (1100,500), and percentage is (0.5,0.5), current value will be (550,250)
         temp.x *= canvas.sizeDelta.x;
         temp.y *= canvas.sizeDelta.y;
 
         //The result is ready, but, this result is correct if canvas recttransform pivot is 0,0 - left lower corner.
         //But in reality its middle (0.5,0.5) by default, so we remove the amount considering cavnas rectransform pivot.
         //We could multiply with constant 0.5, but we will actually read the value, so if custom rect transform is passed(with custom pivot) , 
         //returned value will still be correct.
 
         temp.x -= canvas.sizeDelta.x * canvas.pivot.x;
         temp.y -= canvas.sizeDelta.y * canvas.pivot.y;
 
         return temp;
     }
Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image InsOp · Feb 18, 2017 at 04:28 PM 0
Share

nice solution, I had to remove line 16. and 17. for some reason, then it worked for me!

avatar image gerardB_fr · Mar 14, 2017 at 04:14 PM 0
Share

Perfect for me !

avatar image modernator24 · Dec 13, 2019 at 04:19 PM 0
Share

$$anonymous$$any thanks. I struggled this issue almost a half day, finally found working solution. You saved me, thanks my friend!

avatar image Glitch-TL · Feb 08 at 07:39 PM 0
Share

Thank you bro

avatar image
7

Answer by cmberryau · Mar 24, 2015 at 12:58 AM

I extended Sylos's slightly by making it an extension method to UnityEngine.Canvas itself, giving the user the option to use a non-main camera if they'd like:

 public static class CanvasExtensions
 {
     public static Vector2 WorldToCanvas(this Canvas canvas,
                                         Vector3 world_position,
                                         Camera camera = null)
     {
         if (camera == null)
         {
             camera = Camera.main;
         }
 
         var viewport_position = camera.WorldToViewportPoint(world_position);
         var canvas_rect = canvas.GetComponent<RectTransform>();
 
         return new Vector2((viewport_position.x * canvas_rect.sizeDelta.x) - (canvas_rect.sizeDelta.x * 0.5f),
                            (viewport_position.y * canvas_rect.sizeDelta.y) - (canvas_rect.sizeDelta.y * 0.5f));
     }
 }

It can be called like so:

 // _ui_canvas being the Canvas, _world_point being a point in the world
 
 var rect_transform = _ui_element.GetComponent<RectTransform>();
 
 rect_transform.anchoredPosition = _ui_canvas.WorldToCanvas(_world_point);

You just have to include the namespace the CanvasExtensions class resides in

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Almamu · May 05, 2015 at 09:19 PM 0
Share

Be aware that the Vector2 the function returns is calculated for center anchored GUI elements, when using a different anchor you may run into problems when the element is not in the correct position or even out of screen.

  • 1
  • 2
  • 3
  • ›

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

61 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Place UI element on pointer up position. 1 Answer

How to display notification on notification bar using GCM in Unity? 1 Answer

RectTransform position won't zero 0 Answers

Can I put non-GUI objects into Canvas? 1 Answer

Setting a Rect from another RectTransform 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges