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;
}
}