Unity3D 检测鼠标位置的Sprite像素颜色

news2024/12/22 22:44:04

思路

  1. 获取鼠标所在屏幕坐标(Vector2)
  2. 通过相机ScreenToWorldPoint(Vector3)转为世界坐标 (注意Vector3的z是距离相机的距离,相机需要正交)
  3. 通过SpriteRenderer访问边界Bounds
  4. 通过Bounds.Contain检测世界坐标是否在SpriteBounds内
  5. 通过比例计算来确定在Sprite内的UV坐标,并根据像素长宽确定像素坐标

float pixelX = (worldPositiopn.x - bounds.min.x) / bounds.size.x * bgSprite.texture.width;
float pixelY = (worldPositiopn.y - bounds.min.y) / bounds.size.y * bgSprite.texture.height;

部分编辑器依赖于OdinInspector,不用可以把红线都删了

实现的效果类似这样,根据边界贴图检测鼠标画线位置是否在范围内请添加图片描述

using Sirenix.OdinInspector;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

namespace Yueh0607.ClothOperations
{
    public class CutBehaviour : MonoBehaviour
    {


        [ShowIf("IsRuntime")]
        [ReadOnly]
        [SerializeField]
        Sprite bgSprite, lineStyleSprite, edgeSprite;
        [ShowIf("IsRuntime")]
        [ReadOnly]
        [SerializeField]
        SpriteRenderer bgRenderer, lineStyleRenderer;
        [SerializeField] Color edgeColor = Color.black;




        bool initialized = false;

#if UNITY_EDITOR
        bool IsRuntime() => Application.isPlaying;
#endif

        /// <summary>
        /// 初始化裁剪行为
        /// </summary>
        /// <param name="bgSprite">背景精灵图</param>
        /// <param name="lineStyleSprite">裁剪线样式精灵图</param>
        /// <param name="edgeSprite">边界范围精灵图(RBGA 0-1 使用(0,0,0,1)表示裁剪线范围)</param>
        public void Initialize(Sprite bgSprite, Sprite lineStyleSprite, Sprite edgeSprite)
        {
            this.bgSprite = bgSprite;
            this.edgeSprite = edgeSprite;
            this.lineStyleSprite = lineStyleSprite;

            bool sizeMatch = (lineStyleSprite.texture.width == bgSprite.texture.width && edgeSprite.texture.width == bgSprite.texture.width)
                && (lineStyleSprite.texture.height == bgSprite.texture.height && edgeSprite.texture.height == bgSprite.texture.height);
            bool rectMatch = (lineStyleSprite.rect == bgSprite.rect && edgeSprite.rect == bgSprite.rect);

            if (!sizeMatch) throw new System.Exception("贴图尺寸不合规");
            if (!rectMatch) throw new System.Exception("精灵尺寸不合规");


            DynamicInitialize();

            initialized = true;
        }

        /// <summary>
        /// 动态内容的初始化
        /// </summary>
        private void DynamicInitialize()
        {
            GameObject bg = new GameObject("CutBackgroundImage");
            bg.transform.SetParent(transform);
            bg.transform.position = Vector3.zero;
            bgRenderer = bg.AddComponent<SpriteRenderer>();
            bgRenderer.sprite = bgSprite;
            GameObject lineStyle = new GameObject("LineStyle");
            lineStyle.transform.SetParent(transform);
            lineStyle.transform.position = Vector3.zero;
            lineStyleRenderer = lineStyle.AddComponent<SpriteRenderer>();
            lineStyleRenderer.sprite = lineStyleSprite;
        }

        /// <summary>
        /// 检查裁剪行为初始化
        /// </summary>
        /// <exception cref="System.Exception"></exception>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        private void ExceptionCheck()
        {
            if (!initialized) throw new System.Exception("未初始化裁剪行为!");
        }

        /// <summary>
        /// 将世界坐标转换到像素坐标
        /// </summary>
        /// <param name="worldPositiopn"></param>
        /// <param name="pixelPosition"></param>
        /// <returns></returns>
        public bool TransPoint(Vector2 worldPositiopn, out Vector2Int pixelPosition)
        {
            ExceptionCheck();
            Bounds bounds= bgRenderer.bounds;
            if (bounds.Contains(worldPositiopn))
            {
                //get pixelX and pixelY
                float pixelX = (worldPositiopn.x - bounds.min.x) / bounds.size.x * bgSprite.texture.width;
                float pixelY = (worldPositiopn.y - bounds.min.y) / bounds.size.y * bgSprite.texture.height;



                //float pixelX = (worldPositiopn.x - bounds.) / bgSprite.rect.width * bgSprite.texture.width;
                //float pixelY = (worldPositiopn.y - bgSprite.rect.y) / bgSprite.rect.height * bgSprite.texture.height;
                pixelPosition = new Vector2Int(Mathf.RoundToInt(pixelX), Mathf.RoundToInt(pixelY));
                return true;
            }

            pixelPosition = Vector2Int.zero;
            return false;
        }

        /// <summary>
        /// 判断某个世界坐标是否在裁剪线范围内
        /// </summary>
        /// <param name="worldPosition">Sprite所在的坐标系坐标</param>
        /// <returns></returns>
        public bool IsInEdgeRange(Vector2 worldPosition)
        {
            ExceptionCheck();
            bool result = TransPoint(worldPosition, out Vector2Int pixelPosition);
            if (!result) return false;

            Color color = edgeSprite.texture.GetPixel(pixelPosition.x, pixelPosition.y);
            if (color == edgeColor) return true;

            return false;
        }
    }
}

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

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

相关文章

企业sdwan组网要求:企业使用SD-WAN组网时有哪些要求?

在当今信息时代&#xff0c;企业对于网络的稳定性和高效性要求越来越高。SD-WAN(软件定义广域网)作为 一种新兴的网络技术&#xff0c;为企业提供了更加灵活、可靠和安全的广域网解决方案。在组建企业SD- WAN网络时&#xff0c;有一些关键要求需要考虑。 1. 高可用性&#xff…

全球首发搭载“舱驾一体”的智能座舱,诺博汽车如何引领未来出行?

智能座舱升级战已经全面打响。 一方面&#xff0c;智能座舱已经进入了3.0时代&#xff0c;车企对于差异化要求越来越高&#xff0c;如何进一步提升单一功能体验并进行深度融合&#xff0c;已经成为了智能座舱市场比拼的重点。 另一方面&#xff0c;在5G、车联网、大数据、人工…

Web安全扫描工具:Appscan安装和使用,无偿分享安装包与教程

Appscan 1、简介2、具体使用规则1、常用界面2、工作原理3、设置小技巧 3、实例扫描1、验证码绕过2、越权扫描3、手动绕过验证码扫描 1、简介 AppScan是一款商业化的web安全扫描工具&#xff0c;web扫描领域十分受欢迎 点击此处&#xff0c;先领取资料再阅读&#xff0c;附安装…

LPA*算法图文详解

之前我们看过了A* 算法&#xff0c;知道了A* 算法的基本原理&#xff0c;但是A* 算法的缺陷也很明显&#xff1a;它是离线的路径规划算法&#xff0c;只能一次规划出路径&#xff0c;但是后面路径被改变的话就无法生效了。针对这个问题&#xff0c;人们研究出了D* 算法。D* 算法…

ORAS轻松地在 OCI 注册表中分发工件

什么是ORAS? 词汇大全 ORAS 实际上是使用 OCI Artifacts 的工具。它将媒体类型视为难题的关键部分。容器镜像永远不会被认为是有问题的工件。ORAS 提供 CLI 和客户端库来跨 OCI 兼容的注册表分发工件。 ORAS的特点 ORAS是如何运作的? 能够跨OCI兼容的注册表或OCI图像布局分…

十大服装店收银系统有哪些 好用的服装收银软件推荐

服装店收银系统对于门店和服装卖场来说非常重要&#xff0c;可以提高工作效率。下面是推荐的十大服装店收银系统&#xff0c;供开设服装店的企业选择合适的收银软件用于经营管理。 1、核货宝收银系统 支持快速收银&#xff0c;同时适用于服装行业&#xff0c;能够支持多规格多…

在 React 表单开发时,有时没有必要使用State 数据状态

说到在React中处理表单&#xff0c;最流行的方法是将输入值存储在状态变量中。遵循这种方法的原因之一是因为毕竟它是React&#xff0c;每个人都倾向于使用它附带的hooks。使用hooks可以解决React中的许多问题&#xff0c;但是在处理表单时是否必需呢&#xff1f;让我们来看看。…

基于UWB技术高精度人员定位系统源码

一、UWB定位技术有什么优势&#xff1f; UWB技术解决了困扰传统无线通信技术多年的有关传播方面的重大难题&#xff0c;具有对信道衰落不敏感、发射信号功率谱密度低、截获率低、系统复杂度低、能提供数厘米的定位精度等优点。 1.系统结构简单 UWB系统中的发射器直接用脉冲小…

244:vue+openlayers 显示滚动效果的线段Line

第244个 点击查看专栏目录 本示例的目的是介绍如何在vue+openlayers项目中绘制滚动效果的线段。思路是先画一个直线,然后画一个小点的dashed线段,通过setInterval变更DashOffset的值来生成动画的效果。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果 文…

视频监控/视频汇聚/安防视频监控平台EasyCVR配置集群后有一台显示离线是什么原因?

开源EasyDarwin视频监控TSINGSEE青犀视频平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;在视频监控播放上&#xff0c;TSINGSEE青犀视频安防监控汇聚平台可支持1、4、9、16个画面窗口播放&#xff0c;可同时播放多…

图像语义分割概述

图像语义分割概述 一、图像语义分割概念 图像语义分割&#xff08;Image Semantic Segmentation&#xff09;是一项计算机视觉任务&#xff0c;其目标是将输入的图像分割成多个区域&#xff0c;并为每个像素分配一个语义类别标签&#xff0c;以表示该像素属于图像中的哪个物体…

C++ 友元、重载、继承、多态

友元 关键字&#xff1a;friend 友元的三种实现 全局函数做友元类做友元成员函数做友元 全局函数做友元 //建筑物类 class Building {//goodGay全局函数是Building好朋友&#xff0c;可以访问Building中私有成员friend void goodGay(Building& building); public:Build…

人才测评系统在企业招聘中的应用

人才测评作为招聘工具&#xff0c;已经频繁应用在各大企业中&#xff0c;如今的社会中&#xff0c;人才对于企业而言&#xff0c;可谓是创造产值的基础。换句话说&#xff0c;”企业得人才者、才能得天下”&#xff0c;有了人才之后&#xff0c;企业在行业中才有竞争力。 目前…

Lnmp架构之Redis服务

1、redis部署 停掉mysql服务 如果在纯净的环境下&#xff0c;make的时候需要安装gcc和make redis服务常用命令 2、redis主从同步 复制文件发送到接收主机server2&#xff0c;server3 server2&#xff0c;server3接收到文件后&#xff0c;和11master端一样的配置方法 3、redis主…

网络机顶盒哪个牌子好?经销商盘点线下畅销网络电视机顶盒排名

网络机顶盒是生活必备小家电&#xff0c;我店内经营网络机顶盒已经很多年了&#xff0c;对这个行业有着深入研究&#xff0c;近来看到网友们在讨论网络机顶盒哪个牌子好&#xff0c;我根据店内销量情况&#xff0c;整理了实体店铺热销网络电视机顶盒排名&#xff0c;感兴趣的朋…

循环神经网络——中篇【深度学习】【PyTorch】【d2l】

文章目录 6、循环神经网络6.4、循环神经网络&#xff08;RNN&#xff09;6.4.1、理论部分6.4.2、代码实现 6.5、长短期记忆网络&#xff08;LSTM&#xff09;6.5.1、理论部分6.5.2、代码实现 6.6、门控循环单元&#xff08;GRU&#xff09;6.6.1、理论部分6.6.2、代码实现 6、循…

实现电商跨平台订单每日自动对账

场景描述&#xff1a; 多数商家都存在多电商平台同时经营的情况&#xff0c;而进行订单对账则是相关业务或财务人员的每日必修课。比如商家在天猫&#xff0c;苏宁&#xff0c;1号店&#xff0c;京东等均有运营店铺&#xff0c;每天需要通过各电商后台系统抓单打单&#xff0c…

Android 小组件 AppWidgetProvider

一、相关文档 二、小组件是什么&#xff1f; 三、AppWidget 核心类 AppWidgetProvider 源码解读和原理分析 1、先看 AppWidgetProvider 源码 2、AppWidgetProvider 回调方法分析 onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appW…

索引与切片

索引 生成一个CNN的输入格式张量 a torch.rand(4, 3, 28, 28) &#xff08;batch, channel&#xff0c;high, width)单个索引的方式与python一样 a[0] # 去索引为0的图片即第一张图片 a[0].shape多个索引与python稍微不一样&#xff0c;但很相似 python&#xff1a;a[0][0…

PMP证书在国内已经泛滥了,还有含金量吗?

没有泛滥吧&#xff1f;这个证书现在就是趋向于项目管理人士要去考的呀&#xff0c;也不是考了没用&#xff0c;提升自身个人的能力、找工作方面和晋升加薪方面确实有用呀&#xff0c;不然报名费那么贵&#xff0c;为什么越来越多人考呢&#xff1f; 1、提升自身个人的能力 首…