You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过代码为UI Image添加适配其形状的PolygonCollider2D

解决方案:2D Sprite/UGUI Image 像素级鼠标悬停检测

本文方案覆盖你提到的两种场景需求,无需手动绘制碰撞体,可直接实现透明背景资源的精准命中检测。

场景1:世界空间SpriteRenderer角色(2D世界对象)

无需手动编辑碰撞体,直接读取Sprite自带的物理轮廓生成对应PolygonCollider2D即可,代码示例如下:

using UnityEngine;

[RequireComponent(typeof(SpriteRenderer), typeof(PolygonCollider2D))]
public class AutoPolygonColliderGenerator : MonoBehaviour
{
    void Start()
    {
        SpriteRenderer sr = GetComponent<SpriteRenderer>();
        PolygonCollider2D collider = GetComponent<PolygonCollider2D>();
        // 读取Sprite的物理形状路径
        collider.pathCount = sr.sprite.GetPhysicsShapeCount();
        for (int i = 0; i < collider.pathCount; i++)
        {
            Vector2[] path = new Vector2[sr.sprite.GetPhysicsShapePointCount(i)];
            sr.sprite.GetPhysicsShape(i, path);
            collider.SetPath(i, path);
        }
    }
}

生成碰撞体后直接通过OnMouseEnter/OnMouseExit接口即可检测鼠标悬停事件,触发Tooltip显示逻辑。

场景2:UGUI Image角色(UI界面对象)

Image组件无需适配碰撞体,直接重写UGUI射线检测的命中判断逻辑即可实现像素级检测,核心逻辑是判断悬停位置对应图片像素的alpha值是否大于阈值,代码示例如下:

using UnityEngine;
using UnityEngine.UI;

public class AlphaHitTestImage : Image
{
    [Tooltip("像素alpha大于该值时判定为命中角色区域")]
    public float alphaThreshold = 0.1f;

    public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
    {
        // 先判断是否命中Image矩形区域
        if (!base.IsRaycastLocationValid(screenPoint, eventCamera))
            return false;
        
        // 坐标转换为纹理像素坐标
        RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out Vector2 localPos);
        Rect texRect = sprite.rect;
        int x = Mathf.RoundToInt(localPos.x + rectTransform.pivot.x * rectTransform.rect.width + texRect.x);
        int y = Mathf.RoundToInt(localPos.y + rectTransform.pivot.y * rectTransform.rect.height + texRect.y);
        // 读取像素alpha判断是否命中非透明区域
        Color pixel = sprite.texture.GetPixel(x, y);
        return pixel.a >= alphaThreshold;
    }
}

基础使用步骤

  1. 资源导入设置:所有用到的Sprite导入时勾选Read/Write Enabled,Mesh Type选择Tight,压缩格式选RGBA32避免alpha读取误差
  2. SpriteRenderer场景:将AutoPolygonColliderGenerator脚本挂到角色对象上,运行即可自动生成贴合轮廓的碰撞体
  3. UGUI Image场景:将默认的Image组件替换为AlphaHitTestImage组件,调整alpha阈值到合适数值
  4. 悬停事件绑定:
  • UGUI对象实现IPointerEnterHandler/IPointerExitHandler接口检测悬停:
using UnityEngine;
using UnityEngine.EventSystems;

public class TooltipTrigger : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
    public string characterName;
    public void OnPointerEnter(PointerEventData eventData)
    {
        // 替换为你的Tooltip显示逻辑
        Debug.Log($"显示角色名称:{characterName}");
    }
    public void OnPointerExit(PointerEventData eventData)
    {
        // 替换为你的Tooltip隐藏逻辑
        Debug.Log("隐藏Tooltip");
    }
}
  • SpriteRenderer对象直接用内置事件检测:
private void OnMouseEnter()
{
    // 显示Tooltip
}
private void OnMouseExit()
{
    // 隐藏Tooltip
}

补充说明

你提到的Raycaster2D方案逻辑和上述方案本质一致:射线检测到碰撞区域后,额外判断碰撞点对应像素的alpha值是否达标,UGUI已经封装了IsRaycastLocationValid入口,无需自行实现射线检测逻辑。

内容的提问来源于stack exchange,提问作者Pikachu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 23:06:04