Unity开发绘画板——04.笔刷大小调节
笔刷大小调节
上面的代码中其实我们已经提供了笔刷大小的字段,即brushSize,现在只需要将该字段和界面中的Slider绑定即可,Slider值的范围我们设置为1~20
代码中只需要做如下改动:
public Slider brushSizeSlider; //控制笔刷大小的滑动条
public float brushSize => brushSizeSlider.value; //笔刷大小取滑动条的值
完整代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class Painter : MonoBehaviour
{public RenderTexture renderTexture;public Slider brushSizeSlider;public Texture2D brushTexture; //笔刷纹理public float brushSize => brushSizeSlider.value; //笔刷大小public float resolutionMultiplier = 5; //线性插值密度调节private Vector2 previousMousePos; //记录上一帧鼠标的位置 void Update(){if (Input.GetMouseButtonDown(0)){previousMousePos = Input.mousePosition;}if (Input.GetMouseButton(0)){var mousePosition = Input.mousePosition;DrawLine(previousMousePos, mousePosition);previousMousePos = mousePosition;}}private void DrawLine(Vector2 start, Vector2 end){float distance = Vector2.Distance(start, end);int steps = Mathf.CeilToInt(distance * resolutionMultiplier);for (int i = 0; i <= steps; i++){float t = i / (float)steps;int x = Mathf.FloorToInt(Mathf.Lerp(start.x, end.x, t));int y = Mathf.FloorToInt(Mathf.Lerp(start.y, end.y, t));DrawBrush(x, y);}}private void DrawBrush(int x, int y){Rect brushRect = new Rect(x, y, brushSize, brushSize);Graphics.SetRenderTarget(renderTexture);GL.PushMatrix();GL.LoadPixelMatrix(0, renderTexture.width, 0, renderTexture.height);Graphics.DrawTexture(brushRect, brushTexture);GL.PopMatrix();Graphics.SetRenderTarget(null);}}
效果优化
运行效果如下图,可见虽然笔刷粗细已可以调节,但是在调节过程中,滑动的同时滑动条周围有绘制的线条,这本不该出现的,出现的原因是因为我们监听了鼠标按下的事件来绘制,这导致在操作滑动条的时候,绘制依然在进行。

操作UI时屏蔽绘制
我们需要检测当前的鼠标是否在UI元素上,如果在,则不进行绘制,这可以使用EventSystem的射线检测来实现,如下我们定义一个函数,当光标在UI元素上的时候返回true,否则返回false:
private bool IsPointerOverUIElement()
{PointerEventData eventData = new PointerEventData(EventSystem.current);eventData.position = Input.mousePosition;List<RaycastResult> results = new List<RaycastResult>();EventSystem.current.RaycastAll(eventData, results);return results.Count > 0;
}
我们在鼠标左键点击的时候判断是否在UI元素上,如果在则禁止绘制;
但有个问题,我们用来绘制的RawImage也是UI元素,它铺满整个屏幕,这会导致我们始终没办法绘制,我们可以将其Raycast Target关掉,这样再操作UI元素的时候就不会进行多余的绘制了

完整代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;public class Painter : MonoBehaviour
{public RenderTexture renderTexture;public Slider brushSizeSlider; //控制笔刷大小的滑动条public Texture2D brushTexture; //笔刷纹理public float brushSize => brushSizeSlider.value; //笔刷大小取滑动条的值public float resolutionMultiplier = 5; //线性插值密度调节private Vector2 previousMousePos; //记录上一帧鼠标的位置 private bool startFromUIElement = false; //点击是否是从UI元素上开始的void Update(){//判断光标是否在UI元素上if (Input.GetMouseButtonDown(0)){if (IsPointerOverUIElement()){startFromUIElement = true;}previousMousePos = Input.mousePosition;}if (Input.GetMouseButton(0) && !startFromUIElement){var mousePosition = Input.mousePosition;DrawLine(previousMousePos, mousePosition);previousMousePos = mousePosition;}if (Input.GetMouseButtonUp(0)){startFromUIElement = false;}}private void DrawLine(Vector2 start, Vector2 end){float distance = Vector2.Distance(start, end);int steps = Mathf.CeilToInt(distance * resolutionMultiplier);for (int i = 0; i <= steps; i++){float t = i / (float)steps;int x = Mathf.FloorToInt(Mathf.Lerp(start.x, end.x, t));int y = Mathf.FloorToInt(Mathf.Lerp(start.y, end.y, t));DrawBrush(x, y);}}private void DrawBrush(int x, int y){Rect brushRect = new Rect(x, y, brushSize, brushSize);Graphics.SetRenderTarget(renderTexture);GL.PushMatrix();GL.LoadPixelMatrix(0, renderTexture.width, 0, renderTexture.height);Graphics.DrawTexture(brushRect, brushTexture);GL.PopMatrix();Graphics.SetRenderTarget(null);}private bool IsPointerOverUIElement(){PointerEventData eventData = new PointerEventData(EventSystem.current);eventData.position = Input.mousePosition;List<RaycastResult> results = new List<RaycastResult>();EventSystem.current.RaycastAll(eventData, results);return results.Count > 0;}}
在下一节我将为大家介绍如何调节线条的颜色~
相关文章:
Unity开发绘画板——04.笔刷大小调节
笔刷大小调节 上面的代码中其实我们已经提供了笔刷大小的字段,即brushSize,现在只需要将该字段和界面中的Slider绑定即可,Slider值的范围我们设置为1~20 代码中只需要做如下改动: public Slider brushSizeSlider; //控制笔刷大…...
./mnt/container_run_medium.sh
#!/bin/bash# 清理旧的日志文件 rm -f *.log rm -f nohup.out rm -f cssd.dat# 启动 pwbox_simu 和 MediumBoxBase nohup /mnt/simutools/pwbox_simu /mnt/simutools/pw_box.conf > /dev/null 2>&1 & nohup /mnt/mediumSimu/MediumBoxBase /mnt/mediumSimu/hynn_…...
数学建模研赛总结
目录 前言进度问题四分析问题五分析数模论文经验分享总结 前言 本文为博主数学建模比赛第五天的内容记录,希望所写的一些内容能够对大家有所帮助,不足之处欢迎大家批评指正🤝🤝🤝 进度 今天已经是最后一天了…...
通信工程学习:什么是TCF技术控制设施
TCF(Technical Control Facility):技术控制设施 首先,需要明确的是,通信工程是一门涉及电子科学与技术、信息与通信工程和光学工程学科领域的基础理论、工程设计及系统实现技术的学科。它主要关注通信过程中的信息传输…...
stm32 bootloader跳转程序设计
文章目录 1、bootloader跳转程序设计(1)跳转程序(2)、app程序中需要注意<1>、在keil中ROM起始地址和分配的空间大小<2>、在system_stm32f4xx.c中设置VECT_TAB_OFFSET为需要偏移的地址<3>、main函数中使能中断 总…...
科技赋能环保:静电与光解技术在油烟净化中的卓越应用
我最近分析了餐饮市场的油烟净化器等产品报告,解决了餐饮业厨房油腻的难题,更加方便了在餐饮业和商业场所有需求的小伙伴们。 随着环保政策的不断升级,餐饮行业的油烟治理成为重要课题。油烟净化器的技术革新不仅提升了净化效率,…...
FCA-FineBI试卷答案
1、【判断题】FineBI数据加工建模中只支持文本、数值、日期三种数据类型。 正确答案:A A. 正确 B. 错误 2、【判断题】Excel 支持批量导入,可以一次导入多个 sheet 或 Excel? 正确答案:A A.正确 B. 错误 3、【判断题】FineBI V6.…...
Spring - @Import注解
文章目录 基本用法源码分析ConfigurationClassPostProcessorConfigurationClass SourceClassgetImportsprocessImports处理 ImportSelectorImportSelector 接口DeferredImportSelector 处理 ImportBeanDefinitionRegistrarImportBeanDefinitionRegistrar 接口 处理Configuratio…...
新能源汽车储充机器人:能源高效与智能调度
新能源汽车储充机器人:开启能源高效利用与智能调度的未来之门 随着全球能源危机的日益加剧和环境污染问题的不断恶化,新能源汽车成为了未来交通领域的重要发展方向。然而,新能源汽车的普及不仅需要解决电池技术的瓶颈,还需要构建一…...
【Linux网络】详解TCP协议(2)
🎉博主首页: 有趣的中国人 🎉专栏首页: Linux网络 🎉其它专栏: C初阶 | C进阶 | 初阶数据结构 小伙伴们大家好,本片文章将会讲解 TCP协议的三次握手和四次挥手 的相关内容。 如果看到最后您觉得…...
STM32DMA学习日记
STM32 DMA学习日记 写于2024/9/28晚 文章目录 STM32 DMA学习日记1. DMA简介2. I/O方式2.1 程序查询方式2.2 程序中断方式2.3 DMA方式 3.DMA框图4. 相关寄存器4.1 DMA中断状态寄存器(DMA_ISR)4.2 DMA中断标志清除寄存器(DMA_IFCR)…...
【高性能内存池】page cache 5
page cache 1 page cache的框架2 central cache从page cache申请n页span的过程3 page cache 的结构3.1 page cache类框架3.2 central cache向page cache申请span3.3 获取k页的span page cache的结构和central cache是一样的,都是哈希桶的结构,并且挂载的…...
Vue 3 魔法揭秘:CSS 解析与 scoped 背后的奇幻之旅
文章目录 一、背景二、源码分析transformMain 返回值transformStyle 方法compileStyleAsync 方法scopedPlugin 方法template 添加 __scopeId 三、总结 一、背景 Vue 3 文件编译流程详解与 Babel 的使用 上文分析了 vue3 的编译过程,但是在对其中样式的解析遗留了一…...
如何获取钉钉webhook
第一步打开钉钉并登录 第二步创建团队 并且 添加自定义 机器人 即可获取webhook...
网页WebRTC电话和软电话哪个好用?
关于WebRTC电话与软件电话哪个更好用,这实际上取决于多个因素,并没有一个绝对的答案。不过,我可以根据WebRTC技术的一些特点,以及与传统软件电话相比的优劣势,为你提供一个清晰的对比。 首先,让我们了解一下…...
MySQL Mail服务器集成:如何配置发送邮件?
MySQL Mail插件使用指南?怎么优化 MySQL发邮件性能? MySQL Mail服务器的集成,使得数据库可以直接触发邮件发送,极大地简化了应用架构。AokSend将详细介绍如何配置MySQL Mail服务器,以实现邮件发送功能。 MySQL Mail&…...
【Rockchip系列】官方函数:imcopy
imcopy 函数原型 IM_STATUS imcopy(const rga_buffer_t src,rga_buffer_t dst,int sync 1,int *release_fence_fd NULL);功能说明 imcopy函数用于执行单次快速图像拷贝操作,将图像从源缓冲区拷贝到目标缓冲区。 参数说明 参数描述src[必填] 源图像缓冲区&…...
Matlab实现鲸鱼优化算法优化回声状态网络模型 (WOA-ESN)(附源码)
目录 1.内容介绍 2部分代码 3.实验结果 4.内容获取 1内容介绍 鲸鱼优化算法(Whale Optimization Algorithm, WOA)是一种基于座头鲸捕食行为的群智能优化算法。该算法通过模仿座头鲸使用螺旋形路径和包围猎物的策略来探索和开发解空间,以找到…...
迈威通信闪耀工博会,以创新科技赋能工业自动化
昨日,在圆满落幕的第24届中国国际工业博览会上,迈威通信作为工业自动化与智慧化领域的先行者,以“创新打造新质通信,赋能工业数字化”为主题精彩亮相,向全球业界展示了我们在工业自动化领域的最新成果与创新技术。此次…...
C# DotNetty客户端
1. 引入DotNetty包 我用的开发工具是VS2022,不同工具引入可能会有差异 工具——>NuGet包管理器——>管理解决方案的NuGet程序包 搜索DotNetty 2.新建EchoClientHandler.cs类 用于接收服务器返回数据 public class EchoClientHandler : SimpleChannelIn…...
PX4坐标系全攻略:NED与FRD转换的5个实际应用场景
PX4坐标系实战指南:NED与FRD转换在无人机五大核心场景中的应用 引言 在无人机飞控系统的开发中,坐标系的理解与应用是算法工程师必须跨越的第一道技术门槛。PX4作为目前最主流的开源飞控平台,其采用的NED(North-East-Down…...
一文搞懂训练大模型的数据怎么准备!
谈到大模型,很多人第一反应都是模型参数大、算力强,但其实数据才是大模型真正的底座。没有足够大、足够干净的数据,再先进的模型也发挥不出威力。今天就从数据层面,把大模型训练的几个关键环节梳理清楚。 数据采集与清洗 大模型训…...
蒙纳什大学发现多模态推理模型的“不确定性陷阱“
这项由蒙纳什大学、佐治亚理工学院、康奈尔大学等多所知名学府联合完成的研究发表于2026年3月的《计算机视觉与模式识别》会议,论文编号为arXiv:2603.13366v1。有兴趣深入了解的读者可以通过该编号查询完整论文。当你问一个AI"这张图片里有什么"时&#x…...
3个高效能的核心功能:League-Toolkit开源工具效率提升指南
3个高效能的核心功能:League-Toolkit开源工具效率提升指南 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League-Too…...
从GOPATH到Go Mod:老项目迁移必知的5个文件结构陷阱
从GOPATH到Go Mod:老项目迁移必知的5个文件结构陷阱 当Golang社区在2018年推出Go Modules时,很少有人预料到这个看似简单的包管理工具会成为Go语言发展史上的分水岭。四年后的今天,仍有大量遗留项目困在GOPATH的泥潭中,而迁移过程…...
Vue项目中使用/deep/报错?手把手教你用::v-deep完美解决样式问题
Vue样式穿透难题:从/deep/到::v-deep的优雅升级指南 在Vue生态中,样式作用域管理一直是开发者们津津乐道的话题。当你在使用第三方UI库时,是否遇到过这样的尴尬:明明在本地开发环境调试好的样式,打包后却神秘失效&…...
别再傻傻分不清了!用Simulink手把手带你搞懂导纳控制与阻抗控制的本质区别
导纳控制 vs 阻抗控制:从理论到Simulink实战的深度解析 在机器人控制领域,柔性交互是一个永恒的话题。想象一下,当机械臂需要完成精密装配任务时,既要有足够的刚性保证定位精度,又要在意外碰撞时表现出适当的柔顺性——…...
CssToInlineStyles终极调试指南:解决10个常见错误与性能优化技巧 [特殊字符]
CssToInlineStyles终极调试指南:解决10个常见错误与性能优化技巧 🚀 【免费下载链接】CssToInlineStyles CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very usefull…...
MinerU本地部署安全吗?数据隐私保护实战配置
MinerU本地部署安全吗?数据隐私保护实战配置 1. 引言:当AI遇见你的敏感文档 想象一下这个场景:你有一份包含商业机密的合同PDF,或者一份涉及个人隐私的医疗报告扫描件。你想用AI快速提取里面的关键信息,但又担心把文…...
光场相机入门:Macro Pixel与SAI如何让你的照片秒变3D(附Python代码示例)
光场相机实战指南:用Macro Pixel与SAI技术打造沉浸式3D影像 当你第一次看到光场相机拍摄的照片能在屏幕上自由切换焦点时,那种震撼感就像发现了摄影的新维度。这背后是Macro Pixel和SAI两项核心技术的完美配合——它们让静态图像拥有了动态的视角选择能力…...
