小工具知识网

当前位置: 首页 > 行业知识 > Unity绘画功能实现(包含涂鸦、颜色一键填充、撤销操作、保存图像)

行业知识

Unity绘画功能实现(包含涂鸦、颜色一键填充、撤销操作、保存图像)

2026-11-06 13:16:43 来源:互联网转载

Unity绘画功能实现包含涂鸦、颜色一键填充、撤销操作、保存图像

  • 写在前面
  • 效果
  • 项目地址
  • 关键讲解
  • 写在后面

    写在前面

    项���需要,要实现在图像上进行绘画,看来网上的很多Unity绘画代码,感觉挺复杂的而且功能不全,这里我自己实现了一个在图像上进行绘画的代码,包含了涂鸦、一键填充颜色、撤销上一次操作、保存图片功能。

    本项目是在http://www.qb5200.com/article/391439.html上进行了魔改。

    效果

    左键涂鸦、右键一键填充、空格撤销上一次操作、程序关闭自动保存图像

    项目地址

    https://github.com/hahahappyboy/ImageDrawProject

    关键讲解

    1、图片的设置

    为了让图片可以编辑,在图片的Inspector窗口要把这两个地方改一下

    2、我这里用的是射线检测,没有用UGUI的事件触发API所以要改一下相机和画布的设置

    相机改为正交

    画布改为屏幕空间Camera模式

    只有这样才能进行鼠标点击的射线才能打到图像。

    3、坐标转化,如何获取鼠标点击的图片的哪个像素

    (1)用Vector3 mouseWorldPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition)将鼠标坐标转化为世界坐标.其中Input.mousePosition屏幕坐标的起点位置 左下角为(0,0)点,右上角为(Screen.width,Screen.height) 。mouseWorldPosition的z轴为摄像机的z轴位置。

    (2)再用Vector2 localPos = transform.InverseTransformPoint(mouseWorldPosition);将世界坐标转化为图片的本地坐标位置,z轴直接不要。transformA.InverseTransformPoint(transformB.position)就是获取transfromB相对于transformA的局部坐标。

    此时如果图像为(512,512)大小,则图像左下角(-256,-256)右上角(256,256)

    (3)最后用将坐标转为左下角(0,0)右上角(512,512)这是为了之后便于计算

    float pixelWidth = drawSprite.rect.width;//512float pixelHeight = drawSprite.rect.height;//512float centeredX = localPos.x + pixelWidth / 2;float centeredY = localPos.y + pixelHeight / 2;//左下角(0,0)右上角(512,512)Vector2 pixel_pos = new Vector2(Mathf.RoundToInt(centeredX), Mathf.RoundToInt(centeredY));

    4、获取图片像素

    核心是用currentColorArray = drawableTexture2D.GetPixels32();获取图像的每个点像素值,这个GetPixels32()方法会返回Color32[]的数组,如果图像是(512,512)大小,那么这是数组的大小就为512×512。数组第0个元素为图片左下角的像素,第512×512个元素为图片右上角的像素。这就是为什么我们在3中要进行坐标转化的原因,因为要一一对应。

    5、涂鸦

    在3中知道鼠标点击的是哪个像素点,4中又知道了图像的所有点像素值,找到对应点更改Color32[]数组中的颜色即可,改完了记得设置回图片。

    drawableTexture2D.SetPixels32(currentColorArray);drawableTexture2D.Apply();

    涂鸦代码详见MarkPixelsToColour()函数

    注意一下,为了防止鼠标滑动太快导致涂鸦点间断的问题,这里使用了插值方法,根据前一个点和后一个点的的距离,叉出中间点。

    //计算当前的位置和上一次记录的位置之间的距离,然后平滑的画,这是为了防止鼠标移动太快,画的点不连续float distance = Vector2.Distance(previousDragPosition, pixelPos);float steps = 1 / distance;for (float lerp = 0; lerp     //插值    Vector2 curPosition = Vector2.Lerp(previousDragPosition, pixelPos, lerp);    //画    PenDraw(curPosition);}previousDragPosition = pixelPos;

上一篇:【clickhouse】ClickHouse与MySQL之间实时同步数据(MySQL引擎),将MySQL数据实时同步到clickhouse

下一篇:4minute怎么读音?