当前位置: 首页 > news >正文

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

思路

  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_EDITORbool 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 pixelYfloat 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.lryc.cn/news/174840.html

相关文章:

  • layui input 监听事件
  • 一致性思维链(SELF-CONSISTENCY IMPROVES CHAIN OF THOUGHT REASONING IN LANGUAGE MODELS)
  • 腾讯云16核服务器配置大全_16核CPU型号性能测评
  • HTML中Input elements should have autocomplete attributes的解决方案
  • 2808. 使循环数组所有元素相等的最少秒数;1015. 可被 K 整除的最小整数;1001. 网格照明
  • Python爬虫在Web应用自动化测试中的应用
  • 苹果手机短信删除了怎么恢复?3种有效方法介绍
  • 前端JavaScript中的 == 和 ===区别,以及他们的应用场景,快来看看吧,积累一点知识。
  • 文献阅读:LIMA: Less Is More for Alignment
  • 机器学习第十四课--神经网络
  • React(react18)中组件通信04——redux入门
  • 最新AI创作系统+ChatGPT网站源码+支持GPT4.0+支持ai绘画+支持国内全AI模型
  • react+umi项目中引入antd组件报错:“Button”不能用作 JSX 组件解决方案
  • 常用算法模板
  • 最全跨境独立站建站详细步骤解析
  • 提升群辉AudioStation音乐体验,实现公网音乐播放
  • 虹科分享 | 谷歌Vertex AI平台使用Redis搭建大语言模型
  • VS Code 代码跳转到定义(.js 和 .vue文件跳转)
  • 华为云云耀云服务器L实例评测 | Docker 部署 Reids容器
  • 聚观早报 | 杭州亚运开幕科技感拉满;腾讯官宣启动「青云计划」
  • Linux Gnome桌面无法打开终端Terminal
  • MySQL学习笔记15
  • 6、SpringBoot_项目的打包与运行
  • 图像语义分割概述
  • ViT细节与代码解读
  • Linux中软链接与硬链接的作用、区别、创建、删除
  • 第一章:最新版零基础学习 PYTHON 教程(第十四节 - Python 条件和循环语句–Python 中的 with 语句)
  • 安科瑞AMC16-DETT铁塔jizhan直流电能计量模块,直流计量用
  • WebGL笔记:WebGL中JS与GLSL ES 语言通信,着色器间的数据传输示例:js控制绘制点位
  • 一文读懂 Redis 缓存系统