Unity中解锁图片像素点,动态闭合轨迹检测

Unity中解锁图片像素点,动态闭合轨迹检测

  • 介绍
  • 资源下载
  • 搭建
  • 总结

介绍

因为最近在研究Mane天蚕变的游戏完整逻辑,研究了两套方案做解锁图片的功能,这里我先讲一下我的这个图片像素点的方案解锁图片,这个逻辑其实很简单就是利用划线检测是否轨迹点闭合,然后闭合的点在映射到图片的像素中即可,当然这里需要制作一个shader就是主图层和遮罩层,因为遮罩层的图是动态生成的,所以这块你的像素越大则性能消耗越多也就会卡顿,所以根据实际情况去考量项目需求。

资源下载

项目资源

请添加图片描述

搭建

Canvas模式
在这里插入图片描述
相机模式
在这里插入图片描述
ImageMask为空物体
LineRenderer为对应组件的物体
GameObject为挂载我自定义脚本的对象
RawImage是我需要挂载Shader材质球的对象,同时也需要将图放上去
在这里插入图片描述
在这里插入图片描述
代码
UnlockImageWithShader运行脚本

using UnityEngine;
using UnityEngine.UI;public class UnlockImageWithShader : MonoBehaviour
{public RawImage imageToUnlock; // 需要解锁的图片(使用RawImage)public LineRenderer lineRenderer; // 用于绘制曲线的LineRendererpublic Shader unlockShader; // 自定义Shaderprivate Texture2D maskTexture; // 遮罩纹理private Material unlockMaterial; // 使用Shader的材质void Start(){// 初始化遮罩纹理maskTexture = new Texture2D(256, 256); // 根据需要设置分辨率maskTexture.filterMode = FilterMode.Point;maskTexture.wrapMode = TextureWrapMode.Clamp;ClearMaskTexture(); // 初始化为全黑unlockMaterial = new Material(unlockShader);unlockMaterial.SetTexture("_MainTex", imageToUnlock.texture); // 设置主纹理unlockMaterial.SetTexture("_MaskTex", maskTexture); // 设置遮罩纹理imageToUnlock.material = unlockMaterial; // 应用材质到RawImage// 初始化LineRendererlineRenderer.startWidth = 0.05f;lineRenderer.endWidth = 0.05f;lineRenderer.material = new Material(Shader.Find("Sprites/Default"));lineRenderer.positionCount = 0;}void Update(){if (Input.GetMouseButton(0)){// 将鼠标屏幕坐标转换为UV坐标TVector mousePos = GetMouseUVPosition();points = AddPointUV(mousePos.m_uv);linePoints = AddPointWP(mousePos.m_worldPos);lineRenderer.positionCount = points.Length;lineRenderer.SetPositions(System.Array.ConvertAll(linePoints, v => v));}if (Input.GetMouseButtonUp(0)){if (IsClosedCurve(points)){UnlockArea(points);}points = new Vector2[0]; // 清空点数组linePoints = new Vector3[0];lineRenderer.positionCount = 0; // 清空LineRenderer}}private Vector2[] points = new Vector2[0]; // 存储玩家绘制的点private Vector3[] linePoints = new Vector3[0]; // 存储玩家绘制的点Vector2[] AddPointUV(Vector2 point){Vector2[] newPoints = new Vector2[points.Length + 1];points.CopyTo(newPoints, 0);newPoints[points.Length] = point;return newPoints;}Vector3[] AddPointWP(Vector3 point){Vector3[] newPoints = new Vector3[points.Length + 1];linePoints.CopyTo(newPoints, 0);newPoints[points.Length] = point;return newPoints;}bool IsClosedCurve(Vector2[] points){if (points.Length < 3) return false; // 至少需要3个点才能形成闭合曲线float distance = Vector2.Distance(points[0], points[points.Length - 1]);return distance < 0.05f; // 判断起点和终点是否接近(阈值)}void UnlockArea(Vector2[] points){// 将多边形区域填充为白色for (int y = 0; y < maskTexture.height; y++){for (int x = 0; x < maskTexture.width; x++){Vector2 pixelUV = new Vector2((float)x / maskTexture.width, (float)y / maskTexture.height);if (IsPointInPolygon(pixelUV, points)){Color c = new Color(Color.white.r, Color.white.g, Color.white.b, 1);maskTexture.SetPixel(x, y, c); // 设置为白色(解锁)}}}maskTexture.Apply(); // 应用纹理更改byte[] b = maskTexture.EncodeToPNG();System.IO.File.WriteAllBytes(Application.dataPath + "/t1.png", b);Debug.LogError("Mask texture updated."); // 调试日志}bool IsPointInPolygon(Vector2 point, Vector2[] polygon){int intersections = 0;for (int i = 0; i < polygon.Length; i++){Vector2 p1 = polygon[i];Vector2 p2 = polygon[(i + 1) % polygon.Length];if (point.y > Mathf.Min(p1.y, p2.y)){if (point.y <= Mathf.Max(p1.y, p2.y)){if (point.x <= Mathf.Max(p1.x, p2.x)){float xIntersection = (point.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;if (p1.x == p2.x || point.x <= xIntersection){intersections++;}}}}}return intersections % 2 != 0; // 奇数交点表示点在多边形内}public class TVector {public Vector2 m_uv;public Vector3 m_worldPos;public TVector(Vector2 uv,Vector3 wp){m_uv = uv;m_worldPos = wp;}}TVector GetMouseUVPosition(){// 将鼠标屏幕坐标转换为UV坐标Vector2 mousePos = Input.mousePosition;// 确保传入的摄像机参数正确bool success = RectTransformUtility.ScreenPointToLocalPointInRectangle(imageToUnlock.rectTransform, mousePos, Camera.main, out Vector2 localPoint);RectTransformUtility.ScreenPointToWorldPointInRectangle(imageToUnlock.rectTransform, mousePos, Camera.main, out Vector3 worldPos);// 将局部坐标转换为 UV 坐标Vector2 uv = Rect.PointToNormalized(imageToUnlock.rectTransform.rect, localPoint);return new  TVector (uv, worldPos);}void ClearMaskTexture(){// 将遮罩纹理初始化为全黑Color[] colors = new Color[maskTexture.width * maskTexture.height];for (int i = 0; i < colors.Length; i++){colors[i] = new Color(Color.black.r, Color.black.g, Color.black.b, 0);}maskTexture.SetPixels(colors);maskTexture.Apply();}
}

UnlockImageShader.Shader

Shader "Custom/UnlockImageShader"
{Properties{_MainTex ("Main Texture", 2D) = "white" {} // 主纹理_MaskTex ("Mask Texture", 2D) = "white" {} // 遮罩纹理}SubShader{Tags { "Queue"="Transparent" "RenderType"="Transparent" }LOD 200Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};sampler2D _MainTex;sampler2D _MaskTex;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.uv;return o;}fixed4 frag (v2f i) : SV_Target{fixed4 mainColor = tex2D(_MainTex, i.uv); // 主纹理颜色fixed4 maskColor = tex2D(_MaskTex, i.uv); // 遮罩纹理颜色// 如果遮罩纹理的 alpha 值大于 0.5,显示主纹理,否则显示黑色return maskColor.a > 0.5 ? mainColor : fixed4(0, 0, 0, 1);}ENDCG}}
}

总结

需要的同学们可以去我上面资源下载的位置去下载。
感谢大家的支持!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

buu-ciscn_2019_ne_5-好久不见50

1. 背景分析 目标程序是一个存在漏洞的二进制文件&#xff0c;我们可以通过以下方式利用漏洞获取 shell&#xff1a; 程序中存在 system() 函数&#xff0c;但没有明显的 /bin/sh 字符串。 使用工具&#xff08;如 ROPgadget&#xff09;发现程序中有 sh 字符串&#xff0c;可…

图论part4|827. 最大人工岛、127. 单词接龙、463. 岛屿的周长

827. 最大人工岛 &#x1f517;&#xff1a;827. 最大人工岛 - 力扣&#xff08;LeetCode&#xff09;827. 最大人工岛 - 给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。返回执行此操作后&#xff0c;grid 中最大的岛屿面积是多少&#xff1f;岛屿 由一…

SpeechCraf论文学习

Abstract 核心问题 挑战 语音风格包含细微的多样化信息&#xff08;如情感、语调、节奏&#xff09;&#xff0c;传统基于标签/模板的标注方法难以充分捕捉&#xff0c;制约了语音-语言多模态模型的性能。 数据瓶颈&#xff1a; 大规模数据收集与高质量标注之间存在矛盾&…

SAIL-RK3576核心板应用方案——无人机视觉定位与地面无人设备通信控制方案

本方案以 EFISH-RK3576-SBC工控板 或 SAIL-RK3576核心板 为核心&#xff0c;结合高精度视觉定位、实时通信与智能控制技术&#xff0c;实现无人机与地面无人设备的协同作业。方案适用于物流巡检、农业植保、应急救援等场景&#xff0c;具备高精度定位、低延迟通信与强环境适应性…

PostgreSQL的学习心得和知识总结(一百七十一)|深入理解PostgreSQL数据库之 外连接消除 的使用和实现

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

C语言实现括号匹配检查及栈的应用详解

目录 栈数据结构简介 C语言实现栈 栈的初始化 栈的销毁 栈的插入 栈的删除 栈的判空 获取栈顶数据 利用栈实现括号匹配检查 总结 在编程中&#xff0c;经常会遇到需要检查括号是否匹配的问题&#xff0c;比如在编译器中检查代码的语法正确性&#xff0c;或者在…

【机器学习chp12】半监督学习(自我训练+协同训练多视角学习+生成模型+半监督SVM+基于图的半监督算法+半监督聚类)

目录 一、半监督学习简介 1、半监督学习的定义和基本思想 2、归纳学习 和 直推学习 &#xff08;1&#xff09;归纳学习 &#xff08;2&#xff09;直推学习 3、半监督学习的作用与优势 4、半监督学习的关键假设 5、半监督学习的应用 6、半监督学习的常见方法 7、半…

2024 年第四届高校大数据挑战赛-赛题 A:岩石的自动鉴定

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

基于WebRTC与P2P技术,嵌入式视频通话EasyRTC实现智能硬件音视频交互,适配Linux、ARM、RTOS、LiteOS

EasyRTC不仅仅是一个连接工具&#xff0c;更是一个经过深度优化的通信桥梁。它在嵌入式设备上进行了特殊优化&#xff0c;通过轻量级SDK设计、内存和存储优化以及硬件加速支持&#xff0c;解决了传统WebRTC在嵌入式设备上的适配难题&#xff0c;显著节省了嵌入式设备的资源。 1…

[c语言日寄]字符串进阶:KMP算法

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还是…

Android源码学习之Overlay

在 Android Framework 开发中&#xff0c;Overlay 主要用于修改和替换系统或应用的资源&#xff0c;而无需直接修改源码&#xff0c;与源码解耦。Overlay 机制可以分为 两种类型&#xff1a; 静态 Overlay&#xff08;Static Resource Overlay, SRO&#xff09; 在 编译时 覆…

【MySQL】基本操作 —— DDL

目录 DDLDDL 常用操作对数据库的常用操作查看所有数据库创建数据库切换、显示当前数据库删除数据库修改数据库编码 对表的常用操作创建表数据类型数值类型日期和时间类型字符串类型 查看当前数据库所有表查看指定表的创建语句查看指定表结构删除表 对表结构的常用操作给表添加字…

网络安全需要学多久才能入门?

网络安全是一个复杂且不断发展的领域&#xff0c;想要入行该领域&#xff0c;我们需要付出足够多的时间和精力好好学习相关知识&#xff0c;才可以获得一份不错的工作&#xff0c;那么网络安全需要学多久才能入门?我们通过这篇文章来了解一下。 学习网络安全的入门时间因个人的…

【测试语言基础篇】Python基础之List列表

一、Python 列表(List) 序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字 - 它的位置&#xff0c;或索引&#xff0c;第一个索引是0&#xff0c;第二个索引是1&#xff0c;依此类推。 Python有6个序列的内置类型&#xff0c;但最常见的是列表和元组。序列都可…

编译系统设计原理概述

目录 简介 词法分析 正则表达式 有穷状态自动机 从正则表达式到有穷自动机的转换 单词识别 简介 主要介绍编译系统设计过程中涉及的原理与技术&#xff0c;主要分为前端设计和后端设计两 个模块。前端部分包括词法分析器、语法分析器的构建和语义分析过程的设计…

ArcGIS Pro 车牌分区数据处理与地图制作全攻略

在大数据时代&#xff0c;地理信息系统&#xff08;GIS&#xff09;技术在各个领域都有着广泛的应用&#xff0c;而 ArcGIS Pro 作为一款功能强大的 GIS 软件&#xff0c;为数据处理和地图制作提供了丰富的工具和便捷的操作流程。 车牌数据作为一种重要的地理空间数据&#xf…

前端登录鉴权全解析:主流方案对比与实现指南

文章目录 一、常见登录鉴权方式概览1.1 主流方案对比1.2 技术特性对比 二、Session/Cookie方案2.1 实现原理2.2 代码实现2.3 优缺点分析 三、JWT方案3.1 实现原理3.2 代码实现3.3 优缺点分析 四、OAuth方案4.1 实现原理4.2 代码实现4.3 优缺点分析 五、SSO方案5.1 实现原理5.2 …

算法系列之回溯算法求解数独及所有可能解

有没有对数独感兴趣的朋友呢&#xff1f;数独作为一款经典的逻辑游戏&#xff0c;其目标是在一个9x9的方格中填入数字1至9&#xff0c;确保每一行、每一列以及每一个3x3的子网格中都包含这些数字且不重复。尽管数独的规则看似简单&#xff0c;但编写一个能够自动求解数独的程序…

华为hcia——Datacom实验指南——TCP传输原理和数据段格式

什么是TCP TCP是一种可靠的端到端的传输层协议&#xff0c;仅应用于单波通信。 采用TCP协议作为传输方式的应用层服务&#xff0c;再进行数据传输前&#xff0c;都需要进行TCP协议的创建。 TCP报文的格式 sequence number&#xff08;序列号&#xff09; 占4个字节&#x…

Vlog 片头制作

打开剪映&#xff0c;新建草稿&#xff0c;导入黑色背景。 拉长时间轴&#xff0c;背景时常调整为4.2秒。 添加文本&#xff0c;输入 5 个“|”&#xff0c;每个中间 2 个空格&#xff0c;如下| | | | |&#xff0c;然后手动放大文本&#xff0c;让中间显示出四个间隔。 继续添…