【Unity3D】实现UGUI高亮引导点击

Unity版本2019.4.0f1 Personal <DX11>

cs 复制代码
using UnityEngine;
using UnityEngine.UI;

public class GuideMask : MonoBehaviour, ICanvasRaycastFilter
{
    public Canvas canvas;
    public Transform guideTargetTrans;
    public Image image;
    private Vector3 guideTargetWorldPos;
    private Vector2 lbPos;
    private Vector2 rtPos;
    private Rect rect;

    /// <summary>
    /// ICanvasRaycastFilter接口所实现的方法
    /// </summary>
    /// <param name="sp"></param>
    /// <param name="eventCamera"></param>
    /// <returns></returns>
    public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
    {
        //sp位于屏幕坐标系,(0,0)位于屏幕左下角
        //rect是基于UGUI坐标构建的矩形,UGUI坐标系(0,0)位于屏幕中心, 因此将sp减去一半屏幕宽高得到以屏幕中心为中心点的点
        //简单理解就是sp的中心点是(Screen.width / 2, Screen.height / 2), 实际rect矩形所在坐标系的中心点是(0,0) 故需减去(Screen.width / 2, Screen.height / 2)还原回以(0,0)作为中心点
        //若不转化,不位于同一个坐标系的点和矩形无法进行计算是否处于矩形内。
        Vector2 offsetSp = sp - new Vector2(Screen.width / 2, Screen.height / 2);
        return rect.Contains(offsetSp) ? false : true; //位于矩形内返回false 代表穿透射线, 否则返回true代表正常接收射线

        //穿透射线是指让这个引导黑幕的矩形区域内的射线检测raycast无效化,射线穿透到下一层UGUI 让它下层UI响应点击。
    }

    // Start is called before the first frame update
    void Start()
    {
        guideTargetWorldPos = guideTargetTrans.position;
        //世界转屏幕点
        Vector3 pos = Camera.main.WorldToScreenPoint(guideTargetWorldPos);
        //屏幕点转UGUI坐标系点
        Vector2 localPoint;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.GetComponent<RectTransform>(), pos, Camera.main, out localPoint);
        lbPos = new Vector2(localPoint.x - 250, localPoint.y - 100);
        rtPos = new Vector2(localPoint.x + 250, localPoint.y + 100);
        //注意:Rect原点是左下角,故需偏移localPoint到左下角传入第一个参数, 第二个参数是Size(矩形右上角是原点左下角+Size得到)
        rect = new Rect(localPoint - new Vector2(250, 100), new Vector2(500, 200));
        Material mat = image.material;
        mat.SetVector("_CustomClipRect", new Vector4(lbPos.x, lbPos.y, rtPos.x, rtPos.y));
    }
}
cs 复制代码
Shader "Hidden/GuideImageEffectShader"
{
    Properties
    {        
        _Color ("Color", Color) = (1,1,1,1)
        _CustomClipRect("CustomClipRect", vector) = (0,0,0,0)
    }
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "UnityUI.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 screenPosition : TEXCOORD1;
                float4 vertex : SV_POSITION;                
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.screenPosition = v.vertex;
                o.vertex = UnityObjectToClipPos(v.vertex);                
                o.uv = v.uv;
                return o;
            }
            
            float4 _CustomClipRect;
            fixed4 _Color;

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = _Color;
                col.a *= (1 - UnityGet2DClipping(i.screenPosition.xy, _CustomClipRect));
                return col;
            }
            ENDCG
        }
    }
}
相关推荐
聚客AI14 小时前
🙋‍♀️Transformer训练与推理全流程:从输入处理到输出生成
人工智能·算法·llm
大怪v16 小时前
前端:人工智能?我也会啊!来个花活,😎😎😎“自动驾驶”整起!
前端·javascript·算法
惯导马工18 小时前
【论文导读】ORB-SLAM3:An Accurate Open-Source Library for Visual, Visual-Inertial and
深度学习·算法
骑自行车的码农20 小时前
【React用到的一些算法】游标和栈
算法·react.js
博笙困了20 小时前
AcWing学习——双指针算法
c++·算法
moonlifesudo21 小时前
322:零钱兑换(三种方法)
算法
NAGNIP2 天前
大模型框架性能优化策略:延迟、吞吐量与成本权衡
算法
美团技术团队2 天前
LongCat-Flash:如何使用 SGLang 部署美团 Agentic 模型
人工智能·算法
Fanxt_Ja2 天前
【LeetCode】算法详解#15 ---环形链表II
数据结构·算法·leetcode·链表
侃侃_天下2 天前
最终的信号类
开发语言·c++·算法