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);
}
相关推荐
叶帆13 天前
【YFIOs】用C#开发硬件之设备上云
开发语言·unity·c#
久数君13 天前
AI三维建模工具“造形家”:地理场景三维化的高效解决方案
unity·glb·ai算法·ai三维建模工具·地图框选·造形家·城市建筑模型
会思考的猴子13 天前
Unity VFX 属性 Postion 和 TargetPostion
unity
hai31524754314 天前
九章编程法 · 猜数字游戏 (GW-BASIC 重构版) *
人工智能·microsoft·游戏引擎·游戏程序
心前阳光14 天前
Unity资源导入之自动化资源导入
unity·自动化·游戏引擎
心前阳光14 天前
Unity之2021.3.45f2c1发布安卓程序遇到的问题
android·unity·游戏引擎
纪纯14 天前
PicoVR Unity Integration SDK 3.4 常用交互API
unity·游戏引擎·vr·pico
龙智DevSecOps解决方案14 天前
3A 游戏优化技术栈:如何打通引擎级分析工具与 DevOps 持续集成管线?
unity·性能优化·游戏开发·技术美术·perforce·unrealengine
葛兰岱尔14 天前
从 SolidWorks 到 Three.js,从 Inventor 到 Unity——制造业CAD模型“几何-语义一体化“转换,不再是天方夜谭!
开发语言·javascript·unity
鼎艺创新科技14 天前
三维电子沙盘中OSGB倾斜摄影数据的加载与渲染
游戏引擎·cocos2d