使用 Unity 绘制应用程序

在过去的一周里,我一直在寻找一种使用 Unity 创建应用程序的方法,我将能够在其中创建绘图。

是这样的:

绘图应用

我尝试了几种模拟绘图的方法,但都没有达到我的预期。

您认为实现这一目标的推荐方法是什么?我尝试使用 SetPixel 和 GetPixel,但由于在运行时编辑纹理可能非常慢,我正在寻找更好的方法(如果有的话)。

谢谢。


慕妹3146593
浏览 145回答 1
1回答

汪汪一只猫

我没有用相对较大的纹理对此进行测试,但我用它画了一张快乐的脸,我有评论解释代码中发生了什么,使用它的最佳方法是使用 Unity 菜单并创建一个 RawImage,然后附加此脚本:using UnityEngine;using UnityEngine.UI;[RequireComponent(typeof(RawImage))]public class PaintCanvas : MonoBehaviour{&nbsp; &nbsp; RectTransform rt;&nbsp; &nbsp; RawImage ri;&nbsp; &nbsp; Vector3 bottomLeft = Vector3.zero;&nbsp; &nbsp; Vector3 topRight = Vector3.zero;&nbsp; &nbsp; Texture2D canvas;&nbsp; &nbsp; int width = 0;&nbsp; &nbsp; int height = 0;&nbsp; &nbsp; // Start is called before the first frame update&nbsp; &nbsp; void Start()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Getting the RectTransform, since this is a RawImage, which exists on the canvas and should have a rect transform&nbsp; &nbsp; &nbsp; &nbsp; rt = GetComponent<RectTransform>();&nbsp; &nbsp; &nbsp; &nbsp; if (rt != null)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GetWorldCorners();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // RawImage that we are going to be updating for our paint application.&nbsp; &nbsp; &nbsp; &nbsp; ri = GetComponent<RawImage>();&nbsp; &nbsp; &nbsp; &nbsp; if (ri != null)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CreateTexture2D();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; // Update is called once per frame&nbsp; &nbsp; void Update()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Make sure our stuff is valid&nbsp; &nbsp; &nbsp; &nbsp; if (rt != null)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(ri != null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HandleInput();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; void HandleInput()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Since we can only paint on the canvas if the mouse button is press&nbsp; &nbsp; &nbsp; &nbsp; // May be best to revise this so the tool has a call back for example a&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; // fill tool selected would call its own "Handle" method,&nbsp; &nbsp; &nbsp; &nbsp; if(Input.GetMouseButtonDown(0) || Input.GetMouseButton(0))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vector2Int mousePos = Vector2Int.zero;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // We have input, lets convert the mouse position to be relative to the canvas&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ConvertMousePosition(ref mousePos);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Checking that our mouse is in bounds, which is stored in our height and width variable and as long as it has a "positive value"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(MouseIsInBounds(mousePos))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // This method could be removed to be the tool method I mention above&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // you would pass in the mousePosition, and color similar to this.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // This way each tool would be its "own" component that would be activated&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // through some form of UI.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PaintTexture(mousePos, Color.black); // Also the color you want would be here to...&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Debug.Log(mousePos);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; void PaintTexture(Vector2Int pos, Color color)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // In our method we don't allow transparency and we are just replacing the pixel,&nbsp; &nbsp; &nbsp; &nbsp; canvas.SetPixel(pos.x, pos.y, color);&nbsp; &nbsp; &nbsp; &nbsp; // Applying out change, we dont want to mip levels.&nbsp; &nbsp; &nbsp; &nbsp; // If you are doing some blending or transparency stuff that would be handled by your tool&nbsp; &nbsp; &nbsp; &nbsp; canvas.Apply(false);&nbsp; &nbsp; }&nbsp; &nbsp; bool MouseIsInBounds(Vector2Int mousePos)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // The position is already relative to the texture so if it is >= to 0 and less then the texture&nbsp; &nbsp; &nbsp; &nbsp; // width and height it is in bounds.&nbsp; &nbsp; &nbsp; &nbsp; if(mousePos.x >= 0 && mousePos.x < width)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (mousePos.y >= 0 && mousePos.y < height)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; }&nbsp; &nbsp; void ConvertMousePosition(ref Vector2Int mouseOut)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // The mouse Position, and the RawImage position are returned in the same space&nbsp; &nbsp; &nbsp; &nbsp; // So we can just update based off of that&nbsp; &nbsp; &nbsp; &nbsp; mouseOut.x = Mathf.RoundToInt(Input.mousePosition.x - bottomLeft.x);&nbsp; &nbsp; &nbsp; &nbsp; mouseOut.y = Mathf.RoundToInt(Input.mousePosition.y - bottomLeft.y);&nbsp; &nbsp; }&nbsp; &nbsp; void CreateTexture2D()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Creating our "Draw" texture to be the same size as our RawImage.&nbsp; &nbsp; &nbsp; &nbsp; width = Mathf.RoundToInt(topRight.x - bottomLeft.x);&nbsp; &nbsp; &nbsp; &nbsp; height = Mathf.RoundToInt(topRight.y - bottomLeft.y);&nbsp; &nbsp; &nbsp; &nbsp; canvas = new Texture2D(width, height);&nbsp; &nbsp; &nbsp; &nbsp; ri.texture = canvas;&nbsp; &nbsp; }&nbsp; &nbsp; void GetWorldCorners()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (rt != null)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vector3[] corners = new Vector3[4];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rt.GetWorldCorners(corners);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Setting our corners&nbsp; based on the fact GetCorners returns them in clockwise order starting from BL TL TR BR.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bottomLeft = corners[0];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; topRight = corners[2];&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}我只想指出,取决于你的规模,你移动鼠标的速度有多快,你最终可能会得到点,这是因为这个算法只更新每帧鼠标经过的像素,如果你移动鼠标快于 1 px每帧你都会有间隙,这可以通过存储最后一帧的 mousePosition 来解决,获取这一帧的新位置,并创建一条线,然后更新该线上的所有点。
打开App,查看更多内容
随时随地看视频慕课网APP