Unity镂空图像做法

news2024/11/24 13:28:48

问题和解决方案

现在要完成一个需求,即镂空中间部分的image,外围image可以定义颜色并可选屏蔽点击,而中间的image需要透明且可以穿透,必须不能屏蔽点击。

由此拆分成了两个问题:

1.定义外围image颜色,内部image不绘制

2.外围image可选raycast target,内围image不受raycast target标志位影响。

由此可继承Graphic和ICanvasRaycastFilter来分别实现这个目标。

OnPopulateMesh

继承graphic脚本后重写Graphic.OnPopulateMesh函数,可以在里面去完成重绘操作。与其说不绘制中间的这部分范围,不如说只绘制外面的范围。用VertexHelper.AddTriangle即可完成简单的三角形绘制工作,由此可以根据外image顶点和内image顶点来完成八个三角形的构建绘制工作,如下示意图所示:

因此代码如下所示:

protected override void OnPopulateMesh(VertexHelper vh)
{
    if (innerTrans == null)
    {
        base.OnPopulateMesh(vh);
        return;
    }

    vh.Clear();

    UIVertex vertex = UIVertex.simpleVert;
    vertex.color = color;

    //0 outer左下角
    vertex.position = new Vector3(outerLeftBottom.x, outerLeftBottom.y);
    vh.AddVert(vertex);
    //1 outer左上角
    vertex.position = new Vector3(outerLeftBottom.x, outerRightTop.y);
    vh.AddVert(vertex);
    //2 outer右上角
    vertex.position = new Vector3(outerRightTop.x, outerRightTop.y);
    vh.AddVert(vertex);
    //3 outer右下角
    vertex.position = new Vector3(outerRightTop.x, outerLeftBottom.y);
    vh.AddVert(vertex);
    //4 inner左下角
    vertex.position = new Vector3(innerLeftBottom.x, innerLeftBottom.y);
    vh.AddVert(vertex);
    //5 inner左上角
    vertex.position = new Vector3(innerLeftBottom.x, innerLeftTop.y);
    vh.AddVert(vertex);
    //6 inner右上角
    vertex.position = new Vector3(innerLeftTop.x, innerLeftTop.y);
    vh.AddVert(vertex);
    //7 inner右下角
    vertex.position = new Vector3(innerLeftTop.x, innerLeftBottom.y);
    vh.AddVert(vertex);

    //绘制三角形
    vh.AddTriangle(0, 1, 4);
    vh.AddTriangle(1, 4, 5);
    vh.AddTriangle(1, 5, 2);
    vh.AddTriangle(2, 5, 6);
    vh.AddTriangle(2, 6, 3);
    vh.AddTriangle(6, 3, 7);
    vh.AddTriangle(4, 7, 3);
    vh.AddTriangle(0, 4, 3);
}

IsRaycastLocationValid

继承ICanvasRaycastFilter接口,重写内置的IsRaycastLocationValid即可:

return innerTrans == null || !RectTransformUtility.RectangleContainsScreenPoint(innerTrans, sp, eventCamera);

整体代码:

public class HollowOutMask : Graphic, ICanvasRaycastFilter
{
    [Header("镂空区域")]
    public RectTransform innerTrans;
    RectTransform outerTrans;//背景区域

    Vector3 innerLeftTop = Vector3.zero;//镂空区域的右上角坐标
    Vector3 innerLeftBottom = Vector3.zero;//镂空区域的左下角坐标
    Vector2 outerRightTop = Vector2.zero;//背景区域的右上角坐标
    Vector2 outerLeftBottom = Vector2.zero;//背景区域的左下角坐标

    protected override void Awake()
    {
        base.Awake();

        outerTrans = GetComponent<RectTransform>();
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        if (innerTrans == null)
        {
            base.OnPopulateMesh(vh);
            return;
        }

        vh.Clear();

        UIVertex vertex = UIVertex.simpleVert;
        vertex.color = color;

        //0 outer左下角
        vertex.position = new Vector3(outerLeftBottom.x, outerLeftBottom.y);
        vh.AddVert(vertex);
        //1 outer左上角
        vertex.position = new Vector3(outerLeftBottom.x, outerRightTop.y);
        vh.AddVert(vertex);
        //2 outer右上角
        vertex.position = new Vector3(outerRightTop.x, outerRightTop.y);
        vh.AddVert(vertex);
        //3 outer右下角
        vertex.position = new Vector3(outerRightTop.x, outerLeftBottom.y);
        vh.AddVert(vertex);
        //4 inner左下角
        vertex.position = new Vector3(innerLeftBottom.x, innerLeftBottom.y);
        vh.AddVert(vertex);
        //5 inner左上角
        vertex.position = new Vector3(innerLeftBottom.x, innerLeftTop.y);
        vh.AddVert(vertex);
        //6 inner右上角
        vertex.position = new Vector3(innerLeftTop.x, innerLeftTop.y);
        vh.AddVert(vertex);
        //7 inner右下角
        vertex.position = new Vector3(innerLeftTop.x, innerLeftBottom.y);
        vh.AddVert(vertex);

        //绘制三角形
        vh.AddTriangle(0, 1, 4);
        vh.AddTriangle(1, 4, 5);
        vh.AddTriangle(1, 5, 2);
        vh.AddTriangle(2, 5, 6);
        vh.AddTriangle(2, 6, 3);
        vh.AddTriangle(6, 3, 7);
        vh.AddTriangle(4, 7, 3);
        vh.AddTriangle(0, 4, 3);
    }

    /// <summary>
    /// 过滤掉射线检测
    /// </summary>
    public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
    {
        return innerTrans == null || !RectTransformUtility.RectangleContainsScreenPoint(innerTrans, sp, eventCamera);
    }

    private bool NeedUpdateBounds()
    {
        if (innerTrans == null)
        {
            return false;
        }

        Bounds bounds = RectTransformUtility.CalculateRelativeRectTransformBounds(outerTrans, innerTrans);
        if (innerLeftTop == bounds.max
            && innerLeftBottom == bounds.min
            && outerRightTop == outerTrans.rect.max
            && outerLeftBottom == outerTrans.rect.min)
        {
            return false;
        }
        return true;
    }

    private void UpdateBounds()
    {
        if (innerTrans == null)
        {
            return;
        }
        Bounds bounds = RectTransformUtility.CalculateRelativeRectTransformBounds(outerTrans, innerTrans);
        innerLeftTop = bounds.max;
        innerLeftBottom = bounds.min;
        outerRightTop = outerTrans.rect.max;
        outerLeftBottom = outerTrans.rect.min;
    }

    private void Update()
    {
        if(NeedUpdateBounds())
        {
            UpdateBounds();
            SetAllDirty();
        }
    }
}

注意我们需要赋值一个innerImage transform给这个graphic脚本,作为内image大小和位置控制;而外image则调整挂载这个graphic脚本本身的transform即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1634113.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

政安晨:【Keras机器学习示例演绎】(二十五)—— 使用具有三重损失的连体网络进行图像相似性估计

目录 简介 设置 加载数据集 准备数据 设置嵌入生成器模型 建立连体网络模型 将一切整合在一起 训练 检查网络的学习成果 摘要 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的博客能够…

Django框架之ORM操作

一、选择数据库 1、默认数据库 Django默认的数据库是sqlite3数据库 DATABASES {default: {ENGINE: django.db.backends.sqlite3,NAME: BASE_DIR / db.sqlite3,} }2、指定数据库 修改连接到MySQL数据库 DATABASES {default: {ENGINE: django.db.backends.mysql,# 数据库名…

鸿蒙OpenHarmony【标准系统 烧录】(基于RK3568开发板)

烧录 烧录是指将编译后的程序文件下载到芯片开发板上的动作&#xff0c;为后续的程序调试提供基础。DevEco Device Tool提供一键烧录功能&#xff0c;操作简单&#xff0c;能快捷、高效的完成程序烧录&#xff0c;提升烧录的效率。 RK3568的镜像烧录通过Windows环境进行烧录&…

Oracle-OCR掉盘无法启动集群问题

问题背景&#xff1a; 用户在对一套Oracle11.2.0.4的RAC集群进行OCR掉盘测试&#xff0c;验证NORMAL冗余的OCR磁盘组的可用性。测试通过将udev配置里面的一块OCR盘注释&#xff0c;然后重启服务器集群模拟OCR磁盘组出现掉盘的情况。用户在测试中&#xff0c;注释掉udev配置里面…

嵌入式开发_DMA详解

在嵌入式开发的广阔天地中&#xff0c;MCU是众多开发者手中的利器。而DMA&#xff08;Direct Memory Access&#xff0c;直接内存访问&#xff09;技术&#xff0c;则如同一位高效的快递小哥&#xff0c;穿梭于处理器与外设之间&#xff0c;无需CPU亲自出马&#xff0c;高效地搬…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-8.1

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

【工具】--- Adobe Illustrator 下载-入门绘图

文章目录 软件下载入门项目可看课程 尝试使用Adobe Illustrator&#xff08;设计师常用软件&#xff09;进行科研绘图。 软件下载 阿里云盘下载 入门项目 绘制一个箭头并保持为SVG&#xff0c; 直线->画线->窗口->描边->选择想要的箭头样式->颜色->改为蓝…

众筹商城源码 众筹商品平台 商城加共识元富之路 网上商城众筹

众筹商城源码 众筹商品平台 商城加共识元富之路 网上商城众筹 前端是编译后的&#xff0c;后端PHP&#xff0c;带商城 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/89161734 更多资源下载&#xff1a;关注我。

mybatis工程需要的pom.xml,以及@Data 、@BeforeEach、@AfterEach 的使用,简化mybatis

对 “mybatis - XxxMapper.java接口中方法的参数 和 返回值类型&#xff0c;怎样在 XxxMapper.xml 中配置的问题” 这篇文章做一下优化 这个pom.xml文件&#xff0c;就是上面说的这篇文章的父工程的pom.xml&#xff0c;即&#xff1a;下面这个pom.xml 是可以拿来就用的 <?…

Node.js 版本升级方法

在构建vue项目时&#xff0c;依赖npm&#xff08;Node Package Manager&#xff09;工具&#xff0c;类似于Java项目需要maven管理。而npm是node.js的管理工具&#xff0c;npm依赖node.js环境才能执行。 有时候使用voscode或者其他工具安装vue项目依赖&#xff0c;显示一直处于…

【自然语言处理】Word2VecTranE的实现

作业一 Word2Vec&TranE的实现 1 任务目标 1.1 案例简介 Word2Vec是词嵌入的经典模型&#xff0c;它通过词之间的上下文信息来建模词的相似度。TransE是知识表示学习领域的经典模型&#xff0c;它借鉴了Word2Vec的思路&#xff0c;用“头实体关系尾实体”这一简单的训练目…

【Vue3】Ref与Reactive

3.1【ref 创建&#xff1a;基本类型的响应式数据】 作用&#xff1a;定义响应式变量。语法&#xff1a;let xxx ref(初始值)。返回值&#xff1a;一个RefImpl的实例对象&#xff0c;简称ref对象或ref&#xff0c;ref对象的value属性是响应式的。注意点&#xff1a; JS中操作数…

【在线名字作画HTML源码】

在线名字作画HTML源码 效果图部分源码领取源码下期更新预报 效果图 部分源码 index.htm <!DOCTYPE html> <html> <head> <title>在线名字作画|民间花鸟字|多彩花鸟虫鱼组合书法|藏字画|字谜语|飞帛板书|意匠文字</title> <meta http-equiv&…

Profinet转Modbus网关接称重设备与1200PLC通讯

Profinet转Modbus网关&#xff08;XD-MDPN100&#xff09;是一种能够实现Modbus协议和Profinet协议之间转换的设备。Profinet转Modbus网关可提供单个或多个RS485接口&#xff0c;使用Profinet转Modbus网关将称重设备与西门子1200 PLC进行通讯&#xff0c;可以避免繁琐的编程和配…

【C++】深入了解C++内存管理

个人主页&#xff1a;救赎小恶魔 欢迎大家来到小恶魔频道 好久不见&#xff0c;甚是想念 今天我们要深入讲述类与对象的初始化列表以及隐式类型转换 目录 1.C的内存分布 2.C/C言中动态内存管理方式 1.C语言的管理方式 2.C的管理方式 new delete 3.operator new与ope…

如何删除BigKey

1.2.3、如何删除BigKey BigKey内存占用较多&#xff0c;即便时删除这样的key也需要耗费很长时间&#xff0c;导致Redis主线程阻塞&#xff0c;引发一系列问题。 redis 3.0 及以下版本 如果是集合类型&#xff0c;则遍历BigKey的元素&#xff0c;先逐个删除子元素&#xff0c;…

为什么选择OpenNJet?OpenNJet下一代云原生应用引擎!OpenNJet开发实战!

前言导读 在当今这个数字化转型加速的时代&#xff0c;云原生技术已成为企业和开发者构建现代应用的首选路径。OpenNJet作为新一代云原生应用引擎&#xff0c;在国内外技术社区受到了广泛关注。 本文将深入探讨OpenNJet的特点、优势以及在开发实践中的应用&#xff0c;带您全…

深度学习基础之《TensorFlow框架(16)—神经网络案例》

一、mnist手写数字识别 1、数据集介绍 mnist数据集是一个经典的数据集&#xff0c;其中包括70000个样本&#xff0c;包括60000个训练样本和10000个测试样本 2、下载地址&#xff1a;http://yann.lecun.com/exdb/mnist/ 3、文件说明 train-images-idx3-ubyte.gz: training s…

vscode 配置与插件记录

vscode插件 python PythonPython DebuggerruffisortPylanceJupyterJupyter KeymapJupyter Slide ShowJupyter Cell TagsautoDocstring - Python Docstring Generator ruff isort pylance autodocsting 在setting.json里这么配置&#xff0c;这样你保存时就会自动format…

【酱浦菌-爬虫项目】爬取学术堂论文信息

1. 首先&#xff0c;代码定义了一个名为 url 的变量&#xff0c;它是一个包含三个网址的集合&#xff08;或者说是一个集合的字典&#xff09;。这些网址分别是&#xff1a; - ‘http://www.xueshut.com/lwtimu/127966.html’ - ‘http://www.xueshut.com/lwtimu/12…