4.6 UI Image follow mouse position?

So in my inventory I have this Picker object that’s supposed to pick up items and have them follow the mouse. The picker is an empty object with a background (and eventually the picked up item) as children. The “Picker” is a child of “Inventory” which is a child of my “UI” canvas object. So UI/Inventory/Picker. I was making the picker follow the mouse with:

transform.localPosition = Input.mousePosition - myCanvas.transform.localPosition;

Everything was working fine until I later made some pivot-related changes to the slots and inventory, now the picker doesn’t follow the cursor ‘unless’ I make it a direct parent to UI instead of Inventory, so then I would have UI/Inventory, and UI/Picker, i.e.

UI
-- Inventory  
-- Picker

as opposed to:

UI
-- Inventory
---- Picker

not just that, I also have to anchor the picker to the bottom left and use the same code or just say:

rectTransform.anchoredPosition = Input.mousePosition;

I would like for the Picker to be a child of Inventory and not UI and still be able to follow the mouse position. The new UI isn’t making it easy with all its pivot/anchors, etc concepts.

I thought initially I could just say:

picker.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);

but it’s not that simple it seems…

Here’s a video demonstrating the issue - YouTube - notice how the picker doesn’t follow the exact position of the cursor when I put it under Inventory.

What do I have to do to make the picker follow the mouse’s exact position when the picker is a child of Inventory instead of UI?

Any help is greatly appreciated. Thanks.

NOTE: Inventory is anchored with ‘middle - center’ and has a pivot of ‘0, 1’

Well, if your Canvas its RenderMode is set to ScreenSpaceOverlay, this will actually do :stuck_out_tongue:

transform.position = Input.mousePosition;

But sinse this breaks if you change the Canvas Render mode, the best way I found was

        Vector2 pos;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(myCanvas.transform as RectTransform, Input.mousePosition, myCanvas.worldCamera, out pos);
        transform.position = myCanvas.transform.TransformPoint(pos);

It feels like there should be a better way, but I’m not able to find another that works for all 3 RenderMode’s yet. :frowning: If you use a different render mode for your canvas (Like World Space), this code will only work if the ‘Event Camera’ of the Canvas is not null :wink:

My tooltip won’t follow my mouse. It mostly follows it, but it’s off.

After two hours of reading, trying crap with the canvas scaler, I found the 100% guaranteed way to do it when you have canvas scaler and screen space overlay:

CanvasScaler scaler = GetComponentInParent<CanvasScaler>();
thingToFollowMouse.anchoredPosition = new Vector2(Input.mousePosition.x * scaler.referenceResolution.x / Screen.width, Input.mousePosition.y * scaler.referenceResolution.y / Screen.height);

My reference resolution is 1920x1080 but when I run it in Unity it is 1200x675. I was surprised CanvasScaler.scaleFactor = 1f during runtime in these circumstances, I had thought that was the way to scale my mouse position…

Hey I stumbled across a similar problem and thought lets see where I can go.
Made some Extensions vor the “CANVAS” you can try them out may be there are some bugs included I tested them only once!!! :smiley:

If someone finds a bug or fixes it please post here. ( The names of the extensions are realy long but you know what it does XD )

    #region Canvas
    /// <summary>
    /// Calulates Position for RectTransform.position from a transform.position. Does not Work with WorldSpace Canvas!
    /// </summary>
    /// <param name="_Canvas"> The Canvas parent of the RectTransform.</param>
    /// <param name="_Position">Position of in world space of the "Transform" you want the "RectTransform" to be.</param>
    /// <param name="_Cam">The Camera which is used. Note this is useful for split screen and both RenderModes of the Canvas.</param>
    /// <returns></returns>
    public static Vector3 CalculatePositionFromTransformToRectTransform(this Canvas _Canvas, Vector3 _Position, Camera _Cam)
    {
        Vector3 Return = Vector3.zero;
        if (_Canvas.renderMode == RenderMode.ScreenSpaceOverlay)
        {   
            Return = _Cam.WorldToScreenPoint(_Position);
        }
        else if (_Canvas.renderMode == RenderMode.ScreenSpaceCamera)
        {
            Vector2 tempVector = Vector2.zero;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(_Canvas.transform as RectTransform, _Cam.WorldToScreenPoint(_Position), _Cam, out tempVector);
            Return = _Canvas.transform.TransformPoint(tempVector);
        }

        return Return;
    }

    /// <summary>
    /// Calulates Position for RectTransform.position Mouse Position. Does not Work with WorldSpace Canvas!
    /// </summary>
    /// <param name="_Canvas">The Canvas parent of the RectTransform.</param>
    /// <param name="_Cam">The Camera which is used. Note this is useful for split screen and both RenderModes of the Canvas.</param>
    /// <returns></returns>
    public static Vector3 CalculatePositionFromMouseToRectTransform(this Canvas _Canvas, Camera _Cam)
    {
        Vector3 Return = Vector3.zero;

        if (_Canvas.renderMode == RenderMode.ScreenSpaceOverlay)
        {
            Return = Input.mousePosition;
        }
        else if (_Canvas.renderMode == RenderMode.ScreenSpaceCamera)
        {
            Vector2 tempVector = Vector2.zero;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(_Canvas.transform as RectTransform, Input.mousePosition, _Cam, out tempVector);
            Return = _Canvas.transform.TransformPoint(tempVector);
        }

        return Return;
    }

    /// <summary>
    /// Calculates Position for "Transform".position from a "RectTransform".position. Does not Work with WorldSpace Canvas!
    /// </summary>
    /// <param name="_Canvas">The Canvas parent of the RectTransform.</param>
    /// <param name="_Position">Position of the "RectTransform" UI element you want the "Transform" object to be placed to.</param>
    /// <param name="_Cam">The Camera which is used. Note this is useful for split screen and both RenderModes of the Canvas.</param>
    /// <returns></returns>
    public static Vector3 CalculatePositionFromRectTransformToTransform(this Canvas _Canvas, Vector3 _Position, Camera _Cam)
    {
        Vector3 Return = Vector3.zero;
        if (_Canvas.renderMode == RenderMode.ScreenSpaceOverlay)
        {
            Return = _Cam.ScreenToWorldPoint(_Position);
        }
        else if (_Canvas.renderMode == RenderMode.ScreenSpaceCamera)
        {
            RectTransformUtility.ScreenPointToWorldPointInRectangle(_Canvas.transform as RectTransform, _Cam.WorldToScreenPoint(_Position), _Cam, out Return);
        }
        return Return;
    }
    #endregion