Position UI to mouse position (Make Tooltip panel

2019-02-28 15:07发布

问题:

I made a tooltip panel follow the cursor with

void Update () {
    this.transform.position = Input.mousePosition;  
}

in the Update function.

The panel "lags" behind, moving to cursor position after quarter of a second, and its kind of annoying Is there a better way of doing this? Can i somehow "glue" it to the cursor? Here is how it looks when i move mouse from right to left.

Panel IS under the cursor when mouse is still, it only trails off when moved vigorously.

回答1:

This is a known issue with unity.

While binding mouse position to any gameObject's position, we face lag. This lag is introduced by unity input module's mouse position recording. Reference1, Reference2.

Work Around : You can make your own cursor in game and bind it to mouse position(as you're binding the UI panel). The custom cursor object in game will have the same position as the the panel because both of these objects will derive their position from same source. And you'll get a lag free panel. :)

Remember to hide the default cursor.



回答2:

You can't assign Input.mousePosition; directly to the UI transform. You have to use RectTransformUtility.ScreenPointToLocalPointInRectangle to convert the mouse position and Canvas to the appropriate position the UI can understand.

After that, you use Canvas.transform.TransformPoint(result) to get the final position of the mouse that should be assigned to the UI/Panel position.

This what that code should look like:

public Canvas parentCanvas;

public void Start()
{
    Vector2 pos;

    RectTransformUtility.ScreenPointToLocalPointInRectangle(
        parentCanvas.transform as RectTransform, Input.mousePosition,
        parentCanvas.worldCamera,
        out pos);
}

public void Update()
{
    Vector2 movePos;

    RectTransformUtility.ScreenPointToLocalPointInRectangle(
        parentCanvas.transform as RectTransform,
        Input.mousePosition, parentCanvas.worldCamera,
        out movePos);

    transform.position = parentCanvas.transform.TransformPoint(movePos);
}

Make sure to assign the Canvas to the parentCanvas slot.

EDIT:

With the original image in your question, I thought that the UI you are moving is always on the side of cursor. After the linked video, I just realized the problem is that the there is a delay on when the Object moves to the cursor position.

This is a problem with Unity. Unity is currently redesigning the InputSystem to fix this problem. The current workaround is to disable the cursor with Cursor.visible = false; then use another image with a cursor icon as the cursor.

Find good cursor online and assign it to the mouseCursor slot texture from the Editor..

public Canvas parentCanvas;
public RawImage mouseCursor;

public void Start()
{
    Cursor.visible = false;
}


public void Update()
{
    Vector2 movePos;

    RectTransformUtility.ScreenPointToLocalPointInRectangle(
        parentCanvas.transform as RectTransform,
        Input.mousePosition, parentCanvas.worldCamera,
        out movePos);

    Vector3 mousePos = parentCanvas.transform.TransformPoint(movePos);

    //Set fake mouse Cursor
    mouseCursor.transform.position = mousePos;

    //Move the Object/Panel
    transform.position = mousePos;
}

Finally, you will notice that I don't use Input.mousePosition directly to set the UI position. Don't use it. The reason is that when you change the Canvas RenderMode and assign the Camera, Input.mousePosition won't work but the RectTransformUtility.ScreenPointToLocalPointInRectangle solution should work.