当前位置:   article > 正文

UGUI实现长按显示道具详细信息(类背包道具信息显示)_unity ugui长按图片

unity ugui长按图片

    游戏中很普遍的一个功能,长按道具,显示道具的信息。类似下面这样的一个功能:

    分析一下这个功能需要的知识点:

        1.文本框的长宽根据文本内容自适应;

        2.点击位置转换成实际UI位置(弹窗位置由点击位置决定而不是点击对象的位置决定,后者更简单)

        3.若道具在屏幕边界,则需要动态修改弹窗的位置以及轴点。

    先说一下画布设置,博主在canvas下新加了UIcamera,相机只渲染UI,方式为Orthographic。画布渲染方式为根据ui相机渲染,ui缩放方式为根据屏幕分辨率,画布尺寸为1080*1920,如图

    第一个问题:弹窗由背景父物体image以及内容子物体text组成。首先背景大小是不定的,所以背景image的填充方式应该为sliced,则需要对图片进行切割,切割图片只需要在图片的inspector视图中点击sprite editor按钮进行切割,切割成拉伸时不影响边框即可。然后在父物体中添加组件Vertical Layout Group和Content Size Fitter,其中Content Size Fitter要设置为preferred。Vertical Layout Group根据自身需要设置即可,博主设置如下。子物体不需要添加额外的组件,之后就可以自适应了。记做预设UITip,供下文使用。这里注意的是如果要改子物体text的文本对齐方式,需要改父物体的轴点。

    第二个问题:博主最初的做法是讲鼠标坐标转换为屏幕坐标,然后乘以画布缩放值得到ui坐标,但是这样算的换个分辨率就不对了,不清楚为什么,这一块也不是很熟悉,找不到问题,只能换方法,直接用一个api解决了,博主依旧贴出来原来的算法,希望知道问题的能指点一下

  1. Vector3 pos = Input.mousePosition;
  2. Debug.Log("mousePos:"+pos);
  3. Vector2 pos2d = RectTransformUtility.WorldToScreenPoint(uiCamera, pos);
  4. Vector2 pos2d_1 = pos2d * canvas.transform.localScale.x;
  5. x = pos2d_1.x - Screen.width / 2;
  6. y = pos2d_1.y - Screen.height / 2;
  7. Debug.Log(x+"----"+y);

其中pos2d_1为博主算的坐标,在1080*1920可以,换了其他分辨率就不行了,而且差距非常大。之后博主更换其他方式,一个api直接解决

  1.         Vector2 pos2D_01;
  2. if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, Input.mousePosition, uiCamera, out pos2D_01))
  3. {
  4. Debug.Log(pos2D_01);
  5. }

其实最初发现了这个方法,但是api写错了...后来检查才发现的,很尴尬。pos2D_01坐标即为当前鼠标点击的位置转成的UI坐标,此时只需要将上面的预设UITip 的相对坐标(localposition)设置为pos2D_01即可。

    第三个问题:首先用博主自己的语言解释下轴点pivot,轴点即为物理中心点,recttransform的坐标以及旋转都是根据轴点决定的,对象的坐标即轴点的坐标。假设一个正方形,则左下为(0,0),右上为(1,1)。设置此正方形轴点为(0,1),即以左上为轴点,此时设置正方形坐标为(100,100),则左上点坐标为(100,100)。 博主默认轴点设置为(0,1),也就是UITip是由左向右铺开,即不可能超过左边框(边框指画布边框),判断是否超过右边框只需要判断UITip的x坐标与UITip的width是否大于画布width的1/2(这里建议读者画一个xy坐标系,画出来就很好理解,但是文字表达是真的麻烦,就省过了)。大于则表示超过。假设右边框超过了,则设置UITip为从右向左铺开,即设置轴心的x值为1。这样的话UITip的最右边即是鼠标点击的地方,是不可能超框的。如图


x方向解决了,y方向同理。上面说的还有一个变量是未知的,即UITip的width。有人说直接recttransform.width。博主试了,这样是不行的,因为UITip的width是由text控制的,将text赋值后,text的width是直接生效的,然后才会影响UITip的width,这中间存在一个时间延迟,也就是说,运行这句代码Text.text =“这是个例子”之后,直接获取text的width是没问题的,但是直接获取UITip的width并不正确,但是延时再获取UITip的width就没问题,博主亲测。所以博主说这里有个延时,没办法,这里只好自己算了。上面Vertical Layout Group组件的属性padding为子物体与父物体的各个方向的边距,则父物体的width只需要text的width加上text与父物体的左右边距即可,height同理。之后与画布的长宽相比即可算出是否超框。代码如下

  1. x = pos2D_01.x;
  2. y = pos2D_01.y;
  3. //当到达边界时候的处理,根据不同的情况设置不同的轴点
  4. //先处理左右边界,默认轴点为(0,1),左边界可以不用处理,上边界不用处理
  5. Debug.Log(Screen.width + "**"+Screen.height);
  6. if (x + width > (1080/2) )//右边界,设置轴点x为1
  7. {
  8. Debug.Log("超右边界");
  9. PivotX = 1;
  10. }
  11. if (Mathf.Abs(-y + height) > (1920/2))//下边界,设置轴点y为0
  12. {
  13. Debug.Log("超下边界");
  14. PivotY = 0;
  15. }

注意这里为什么会跟1080/2 和1920/2比较,这是因为画布的尺寸设置为如此,而画布的尺寸是不随分辨率改变而改变的,画布只是会根据不同的分辨率进行相应的缩放显示,但是实际尺寸还是最初设定的。这是博主的理解,不清楚是否正确,但是博士实验结果是这样的。有不对的欢迎指正,谢谢。

    整个过程就是这个样子,博主粘贴一下整个代码

  1. public class UITip : MonoBehaviour
  2. {
  3. public Text msgTxt;
  4. public Canvas canvas;
  5. public Camera uiCamera;
  6. private RectTransform recTran;
  7. private VerticalLayoutGroup group;
  8. private float width;//物体宽度
  9. private float height;//物体长度
  10. private float x;//x坐标
  11. private float y;//y坐标
  12. private int PivotX;//轴点x坐标
  13. private int PivotY;//轴点y坐标
  14. void Start()
  15. {
  16. recTran = transform as RectTransform;
  17. group = transform.GetComponent<VerticalLayoutGroup>();
  18. }
  19. public void Show(string msg)
  20. {
  21. PivotX = 0;
  22. PivotY = 1;
  23. msgTxt.text = msg;
  24. //设置弹窗最外面渲染
  25. transform.SetAsLastSibling();
  26. //计算recttransform的width与height,根据子物体文本长度和vertical layout group 的padding计算,直接获取的话获取的不对,延时获取才是对的,但子物体文本的直接获取是对的
  27. width = msgTxt.preferredWidth + group.padding.left + group.padding.right;
  28. height = msgTxt.preferredHeight + group.padding.top + group.padding.bottom;
  29. Debug.Log(width + "---" + height);
  30. #region
  31. Vector2 pos2D_01;
  32. if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, Input.mousePosition, uiCamera, out pos2D_01))
  33. {
  34. Debug.Log(pos2D_01);
  35. }
  36. x = pos2D_01.x;
  37. y = pos2D_01.y;
  38. //当到达边界时候的处理,根据不同的情况设置不同的轴点
  39. //先处理左右边界,默认轴点为(0,1),左边界可以不用处理,上边界不用处理
  40. Debug.Log(Screen.width + "**"+Screen.height);
  41. if (x + width > (1080/2) )//右边界,设置轴点x为1
  42. {
  43. Debug.Log("超右边界");
  44. PivotX = 1;
  45. }
  46. if (Mathf.Abs(-y + height) > (1920/2))//下边界,设置轴点y为0
  47. {
  48. Debug.Log("超下边界");
  49. PivotY = 0;
  50. }
  51. recTran.pivot = new Vector2(PivotX, PivotY);
  52. transform.localPosition = pos2D_01;
  53. return;
  54. #endregion
  55. }
  56. }
    总感觉上面有些地方的解释不正确,只是自己看到的,所以希望发现问题的不吝赐教,在此谢过。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/108184
推荐阅读
相关标签
  

闽ICP备14008679号