将UI定位到鼠标位置(让工具提示面板跟随光标移动)

5
我制作了一个提示面板,跟随光标移动。
void Update () {
    this.transform.position = Input.mousePosition;  
}

在Update函数中。
面板“滞后”,在四分之一秒后才移动到光标位置,这有点烦人。有没有更好的方法?我能否以某种方式将其“粘”到光标上?
当我从右向左移动鼠标时,它的样子如下所示:enter image description here 当鼠标静止时,面板在光标下方,只有在剧烈移动时才会脱落。

1
在Unity中尝试过,没有看到任何延迟。请分享有关您的应用程序、面板和脚本的更多信息。 - Mukesh Saini
如果我放置一个30像素乘30像素的面板,并让它跟随光标移动,使用简单的Input.mousePosition,我可以轻松地通过快速移动鼠标来超越它。其他人不是这种情况吗?我尝试创建空项目,但仍然有同样的问题。我需要一个30像素乘30像素的面板始终在光标下方。 - user2998964
提示面板,它是UI还是普通的GameObject?你所说的“慢”是什么意思?提示不在鼠标光标所在位置吗?我认为你应该放一张截图。 - Programmer
只是一个面板对象。 - user2998964
请忽略我的第一条评论。当使用UI面板时,我可以看到延迟。 - Mukesh Saini
4个回答

10
您不能直接将 Input.mousePosition; 赋值给 UI transform。您需要使用RectTransformUtility.ScreenPointToLocalPointInRectangle 将鼠标位置和画布转换为UI可以理解的适当位置。
之后,您可以使用Canvas.transform.TransformPoint(result) 获取应分配给 UI/面板位置的鼠标最终位置。
下面是代码示例:
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);
}

请确保将Canvas分配给parentCanvas插槽。
编辑:
根据您问题中的原始图像,我认为您移动的UI始终在光标侧边。在观看了链接视频之后,我才意识到问题是对象移动到光标位置时存在延迟。
这是Unity的问题。Unity目前正在重新设计InputSystem以解决此问题。当前的解决方法是使用Cursor.visible = false;禁用光标,然后使用另一个带有光标图标的图像作为光标。
在网上找到好的光标并将其分配给编辑器中的mouseCursor插槽纹理。
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;
}

最后,你会注意到我没有直接使用Input.mousePosition来设置UI位置。不要使用它。原因是当你改变Canvas RenderMode并分配摄像头时,Input.mousePosition将无法工作,但RectTransformUtility.ScreenPointToLocalPointInRectangle的解决方案应该可行。


同样的效果,面板跟随光标滞后 :( - user2998964
它在我的端上运行顺畅。你的相机投影模式是什么?Canva的渲染模式是什么?你使用的Unity版本是什么? - Programmer
透视 - 叠加 - 5.4.0 - user2998964
我正在使用相同的设置,UI始终在鼠标位置上方。这是正确的方法,自UI发布以来一直有效。我刚刚再次测试了它,它仍然有效。你做错了什么。选择你要移动的面板,点击RectTranform,按住Shift并单击中心以居中锚点。我认为这就是你现在遇到的问题。 - Programmer
也许是你移动得不够快?或者可能是因为我的鼠标是USB接口的原因?无论如何,这里有一个例子:https://www.youtube.com/watch?v=3cV2tjq51n8 - user2998964
我尝试了所有的方法,但对我来说没有任何区别。 - xcrypt

3
这是Unity的已知问题。
在将鼠标位置绑定到任何gameObject的位置时,我们会遇到延迟。这种延迟是由Unity输入模块的鼠标位置记录引入的。参考1参考2
解决方法:您可以在游戏中制作自己的光标,并将其绑定到鼠标位置(就像绑定UI面板一样)。游戏中的自定义光标对象将具有与面板相同的位置,因为两个对象都将从同一源派生它们的位置。这样,您将获得一个无延迟的面板。 :)
记得隐藏默认光标。

有没有已知的解决方法? 我猜这不是那么关键。 - user2998964
@程序员,当你编辑你的答案时,我正在写我的答案。请不要想得太多,最重要的是我们已经找到了解决这个问题的方案。无论如何,我们都有同样的解决办法,使它变得完美可靠;)。 - Mukesh Saini

1

Unity 2021 - 针对所有对于在2021年中希望有一个跟随鼠标位置的工具提示(Unity GUI)感兴趣的人。

上面发布的使用 RectTransformUtility 的解决方案不起作用,或者它取决于一些在帖子中缺失的画布设置细节。

在 Unity 2021 中有效的方法是:

画布设置:

enter image description here

工具提示是一个简单的UI对象(面板或其他),作为画布的子元素,具有以下设置:

enter image description here

并且附有以下附加的脚本:
tooltip_rect_transform_ref.anchoredPosition = Input.mousePosition / tooltip_parent_canvas.transform.localScale.x;

在编辑器和构建版本中都能正常工作,适用于不同的分辨率。


1

我重新挖掘这个问题,因为今天我也有同样的问题。

关于@zizu_zaza提出的解决方案,它没有考虑到不同的纵横比(至少当Canvas Scaler屏幕匹配比率不为1.0或0.0时)。仅通过画布缩放来缩放鼠标位置仅适用于相同方面的不同分辨率。

要考虑鼠标位置缩放中的分辨率和纵横比,请执行以下操作:

Vector2 mergedFactors = new Vector2(
      (canvas.transform as RectTransform).sizeDelta.x / Screen.width,
      (canvas.transform as RectTransform).sizeDelta.y / Screen.height);
//x and y -> *= (RefX/ScreenWidth) * (CanvasWidth/RefX)
tooltip.anchoredPosition = mousePos * mergedFactors;

//Short maths explanation:
//CanvasScaler scaler = GetComponentInParent<CanvasScaler>();
//Vector2 scaleFactors = new Vector2(
//    scaler.referenceResolution.x / Screen.width, 
//    scaler.referenceResolution.y / Screen.height);
//Vector2 aspectFactors = new Vector2(
//    (canvas.transform as RectTransform).sizeDelta.x / scaler.referenceResolution.x,
//    (canvas.transform as RectTransform).sizeDelta.y / scaler.referenceResolution.y);
//Vector2 mergedFactors = scaleFactors * aspectFactors
//
//->scale reference resolution by actual screen resolution
//->scale canvas "size" (which adjusts to aspect) by reference resolution
//->combine both: reference resolution multi & div cancel out

这将允许工具提示(或任何其他UI对象)在任何分辨率和纵横比下跟随鼠标。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接