unity的背包滑动组件中道具的提示框被裁剪的问题

1.简单粗暴方法:

不使用最上层的canvas进行渲染,每个提示框单独挂载一个canvas渲染就可见了,不会被遮挡和裁剪了。

但为了"防止裁剪"而给每个道具都挂一个 Canvas,相当于"用大炮打蚊子"

问题:

每个道具都是一个独立的 Canvas。UI 系统需要为每一个 进行独立的布局计算、网格重建和批处理准备,无论其是否激活。这会产生大量固定的 CPU 开销 (管理 Canvas)和潜在的 GPU 开销(大量不可合并的小批次),在背包打开、滚动时会造成卡顿。

2.单一顶层Canvas:

  • 造成这个问题的核心原因是每个道具item都有自己的子对象,提示框。
  • 再滑动列表中会受到影响。
  • 那我们就将提示框移出Viewport的遮挡节点。
  • 那现在需要解决的问题就是控制提示框的位置定位,和显示隐藏
思路:
  1. 结构解耦

    • 将提示框预制体从所有道具项中彻底移除

    • UI顶层 (例如与背包面板同级,可以更具需要移动)创建一个唯一的、共享的提示框GameObject。它就挂在一个公共的、高级别的 Canvas 下。

  2. 事件驱动控制

    • 编写一个单例或管理器(如 TooltipManager),专门控制这个唯一的提示框。

    • 在每个道具的脚本上,继续处理鼠标悬停(OnPointerEnter)和离开(OnPointerExit)事件。

    • 鼠标悬停时 ,道具脚本不自己创建提示框 ,而是向 TooltipManager 发送请求:"请显示提示框,内容是我,我的位置是这里"。

    • TooltipManager 收到请求后,立刻隐藏当前可能正在显示的提示框,然后用新数据和位置更新那个唯一的提示框实例,再显示它。

    • 鼠标离开时,道具脚本通知管理器"隐藏提示框"。管理器可以加一个延时隐藏或判断鼠标是否已移到提示框本身上。

这个交互事件就不多说了,可以更具自己的需求实现,不管是点击,滑动还是鼠标悬停等。

简单列举几个接口,滑动,点击的,实现后挂载在ScrollRect上就可以,不能挂载到其子对象上,这些事件是不被ScrollRect继续向下传递的。

cs 复制代码
public class EventHandler : MonoBehaviourAutoRelease, IPointerUpHandler, IPointerDownHandler, IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    public Action<PointerEventData> OnBeginDragAction;

    public Action<PointerEventData> OnDragAction;

    public Action<PointerEventData> OnEndDragAction;

    public Action<PointerEventData> OnPointerClickAction;

    public Action<PointerEventData> OnPointerDownAction;

    public Action<PointerEventData> OnPointerUpAction;



    public void OnBeginDrag(PointerEventData eventData)
    {
        OnBeginDragAction?.Invoke(eventData);
    }

    public void OnDrag(PointerEventData eventData)
    {
        OnDragAction?.Invoke(eventData);        
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        OnEndDragAction?.Invoke(eventData);
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        OnPointerClickAction?.Invoke(eventData);
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        OnPointerDownAction?.Invoke(eventData);
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        OnPointerUpAction?.Invoke(eventData);
    }
}

列举下定位的问题把

  • AdjustTooltipPosition的内容就根据自己的需要去修改了

  • 位置实现的更具item相对于viewport的本地坐标的判断,修改了提示框背景板的朝向和位置效果如下图:

  • 其中使用到一个重要的API:InverseTransformPoint,将对象的世界坐标转换为相对目标的本地坐标的方法。其锚点是(0.5,0.5)

  • 因为我是将提示框放在,backpackScrollRect滚动组件下,所以转换的本地坐标可以直接赋值给提示框,实现定位。

cs 复制代码
[Header("背包引用")]
public ScrollRect backpackScrollRect;
public RectTransform viewportRect;
public RectTransform contentRect;



public RectTransform ItemTipObj;    // 提示框

    

public void ShowTooltip()
{
    RectTransform itemRect = transform.GetComponent<RectTransform>();
    if (itemRect == null) return;

    Vector2 itemInViewportLocalPos = backpackScrollRect.GetComponent<RectTransform>().InverseTransformPoint(itemRect.position);
    float viewportHalfWidth = backpackScrollRect.GetComponent<RectTransform>().rect.width / 2; 
    float itemRelativeX = Mathf.InverseLerp(-viewportHalfWidth, viewportHalfWidth, itemInViewportLocalPos.x + itemRect.rect.width / 2);
    itemRelativeX = Mathf.Clamp01(itemRelativeX);

    bool isLeftEdge = itemRelativeX < 0.5; 
    bool isRightEdge = itemRelativeX > 0.5; 

    
    AdjustTooltipPosition(itemRect, isLeftEdge, isRightEdge);
}


public void AdjustTooltipPosition(RectTransform itemRect, bool isLeft, bool isRight)
{
    Vector2 itemInViewportLocalPos = backpackScrollRect.GetComponent<RectTransform>()
        .InverseTransformPoint(itemRect.position);

    float pos = 0;
    if (isLeft) pos = 80;
    else pos = -80;

    ItemTipObj.localPosition = new Vector3(itemInViewportLocalPos.x + pos, itemInViewportLocalPos.y + itemRect.rect.height, 0);
    ItemTipObj.Find("Bg_RectTransform").transform.localScale = new Vector3(isLeft ? 1 : -1, 1, 1);
}
相关推荐
爱搞虚幻的阿恺2 天前
Niagara粒子系统-超炫酷的闪电特效(加餐 纸牌螺旋上升效果)
游戏·游戏引擎
_Li.2 天前
Simulink - 6DOF (Euler Angles)
人工智能·算法·机器学习·游戏引擎·cocos2d
weixin_424294672 天前
Unity 调用Steamworks API 的 SteamUserStats.RequestCurrentStats()报错
unity·游戏引擎·steamwork
HoFunGames2 天前
Unity小地图,Easy Minimap System MT-GPS插件
unity·游戏引擎
wy3258643642 天前
Unity 新输入系统InputSystem(基本操作)
unity·c#·游戏引擎
WarPigs2 天前
着色器multi_compile笔记
unity·着色器
ECHO飞跃 0122 天前
Unity2019 本地推理 通义千问0.5-1.5B微调导入
人工智能·深度学习·unity·llama
Unity游戏资源学习屋2 天前
【Unity UI资源包】GUI Pro - Casual Game 专为休闲手游打造的专业级UI资源包
ui·unity
冰凌糕2 天前
Unity3D Shader 顶点法线外扩实现描边效果
unity
星和月2 天前
Untiy使用说明
c#·游戏引擎