UGUI进阶知识[三]不规则image 区域点击 以及 自定义简单组件的知识

UGUI默认的image是方形的
一般来说只要鼠标或者触摸在方形里面
加了button组件的话
响应点击是少不了的

有时我们需要的是一些看不见的地方就不要响应了
比如一些周围是透明的图片
点击到透明部分最好不要响应

查看UGUI源码可以发现
UGUI本身里面有个解决方案
alphaHitTestMinimumThreshold 属性
只是这个属性默认是0 将其设置为其他值 图片透明度低于这个值的部分就不会响应点击

 GetComponent<Image>().alphaHitTestMinimumThreshold = 0.1f;

需要注意的是:

  • 这需要这个image使用的图片开启read write enable属性 这会造成图片在内存中的大小变成原先的两倍
  • 这类型的图片不能打进UGUI图集里面

这里介绍的不规则区域点击不包括镂空的
镂空可以考虑自定义UIMask里面的实现
UGUI进阶知识[二]自定义多边形image image精确点击以及 不继承monobehaviour的类如何在inspector显示自定义变量的编辑器知识

不规则区域点击的思路:
在image上面挂载一个不规则碰撞体
不规则碰撞体需要自己编辑合适形状
然后点击的时候判断是否在碰撞体内部即可

下面是代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CustomImage : Image
{
    private PolygonCollider2D _polygon;

    private PolygonCollider2D Polygon
    {
        get
        {
            if (_polygon == null)
                _polygon = GetComponent<PolygonCollider2D>();

            return _polygon;
        }   
    }

    /// <summary>
    /// 这个函数基本上只要鼠标浮动在上面 
    /// 就基本会每帧调用
    /// 所以GetComponent之类的方法在里面控制只调用一次
    /// </summary>
    /// <param name="screenPoint"></param>
    /// <param name="eventCamera"></param>
    /// <returns></returns>
    public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
    {
        Vector3 point;
        //将指针的屏幕坐标转换成世界坐标
        RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, screenPoint, eventCamera, out point);
        //传入参数应该是世界坐标
        return Polygon.OverlapPoint(point);
    }
}


下面的部分是自定义组件的代码,放在Editor下面

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;

public class CustomImageEditor : Editor
{
    //unity引擎内部的UI 的 layer 默认是5
    //可以打开inspector面板查看
    private const int UI_LAYER = 5;

    //声明在unity顶部建立一个创建的快捷方式
    //只有静态方法能用这个属性
    //priority代表排列的优先级
    //一般越小越靠前 默认1000
    //这里如果把CustomImage改成Image 会覆盖掉unity的image组件
    //也就是image组件完全由自己定义了 
    [MenuItem("GameObject/UI/CustomImage", priority = 0)]
    private static void AddImage()
    {

        Transform canvasTrans = GetCanvasTrans();

        Transform image = AddCustomImage();

        if (Selection.activeGameObject!= null && Selection.activeGameObject.layer == UI_LAYER)
        {
            image.SetParent(Selection.activeGameObject.transform);
        }
        else
        {
            image.SetParent(canvasTrans);
        }
       
        image.localPosition = Vector3.zero;
    }

    private static Transform GetCanvasTrans()
    {
        Canvas canvas = GameObject.FindObjectOfType<Canvas>();
        if (canvas == null)
        {
            GameObject canvasObj = new GameObject("Canvas");
            SetLayer(canvasObj);
            canvasObj.AddComponent<RectTransform>();
            //设置RenderMode是一直贴着屏幕的
            canvasObj.AddComponent<Canvas>().renderMode = RenderMode.ScreenSpaceOverlay;
            canvasObj.AddComponent<CanvasScaler>();
            canvasObj.AddComponent<GraphicRaycaster>();
            return canvasObj.transform;
        }
        else
        {
            return canvas.transform;
        }
    }

    private static Transform AddCustomImage()
    {
        GameObject image = new GameObject("Image");
        SetLayer(image);
        image.AddComponent<RectTransform>();
        image.AddComponent<PolygonCollider2D>();
        image.AddComponent<Button>();
        image.AddComponent<CustomImage>();

        return image.transform;
    }

    private static void SetLayer(GameObject ui)
    {
        ui.layer = UI_LAYER;
    }
}

发布了84 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43149049/article/details/102998599