在过去的一周中,我一直在寻找一种使用Unity创建应用程序的方法,在其中可以创建图形。
类似这样的东西:
我尝试了几种模拟绘图的方法,但没有一个能达到我的预期。
您认为实现此目标的推荐方法是什么? 我尝试使用SetPixel和GetPixel,但是由于在运行时编辑纹理可能非常缓慢,因此我在寻找更好的方法(如果有的话)。
谢谢。
答案 0 :(得分:1)
我还没有用较大的纹理测试过它,但是我用它画了一张快乐的脸,我有评论来解释代码中发生了什么,最好的使用方法是使用Unity Menu并创建RawImage然后附加此脚本:
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(RawImage))]
public class PaintCanvas : MonoBehaviour
{
RectTransform rt;
RawImage ri;
Vector3 bottomLeft = Vector3.zero;
Vector3 topRight = Vector3.zero;
Texture2D canvas;
int width = 0;
int height = 0;
// Start is called before the first frame update
void Start()
{
// Getting the RectTransform, since this is a RawImage, which exists on the canvas and should have a rect transform
rt = GetComponent<RectTransform>();
if (rt != null)
{
GetWorldCorners();
}
// RawImage that we are going to be updating for our paint application.
ri = GetComponent<RawImage>();
if (ri != null)
{
CreateTexture2D();
}
}
// Update is called once per frame
void Update()
{
// Make sure our stuff is valid
if (rt != null)
{
if(ri != null)
{
HandleInput();
}
}
}
void HandleInput()
{
// Since we can only paint on the canvas if the mouse button is press
// May be best to revise this so the tool has a call back for example a
// fill tool selected would call its own "Handle" method,
if(Input.GetMouseButtonDown(0) || Input.GetMouseButton(0))
{
Vector2Int mousePos = Vector2Int.zero;
// We have input, lets convert the mouse position to be relative to the canvas
ConvertMousePosition(ref mousePos);
// 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"
if(MouseIsInBounds(mousePos))
{
// This method could be removed to be the tool method I mention above
// you would pass in the mousePosition, and color similar to this.
// This way each tool would be its "own" component that would be activated
// through some form of UI.
PaintTexture(mousePos, Color.black); // Also the color you want would be here to...
}
Debug.Log(mousePos);
}
}
void PaintTexture(Vector2Int pos, Color color)
{
// In our method we don't allow transparency and we are just replacing the pixel,
canvas.SetPixel(pos.x, pos.y, color);
// Applying out change, we dont want to mip levels.
// If you are doing some blending or transparency stuff that would be handled by your tool
canvas.Apply(false);
}
bool MouseIsInBounds(Vector2Int mousePos)
{
// The position is already relative to the texture so if it is >= to 0 and less then the texture
// width and height it is in bounds.
if(mousePos.x >= 0 && mousePos.x < width)
{
if (mousePos.y >= 0 && mousePos.y < height)
{
return true;
}
}
return false;
}
void ConvertMousePosition(ref Vector2Int mouseOut)
{
// The mouse Position, and the RawImage position are returned in the same space
// So we can just update based off of that
mouseOut.x = Mathf.RoundToInt(Input.mousePosition.x - bottomLeft.x);
mouseOut.y = Mathf.RoundToInt(Input.mousePosition.y - bottomLeft.y);
}
void CreateTexture2D()
{
// Creating our "Draw" texture to be the same size as our RawImage.
width = Mathf.RoundToInt(topRight.x - bottomLeft.x);
height = Mathf.RoundToInt(topRight.y - bottomLeft.y);
canvas = new Texture2D(width, height);
ri.texture = canvas;
}
void GetWorldCorners()
{
if (rt != null)
{
Vector3[] corners = new Vector3[4];
rt.GetWorldCorners(corners);
// Setting our corners based on the fact GetCorners returns them in clockwise order starting from BL TL TR BR.
bottomLeft = corners[0];
topRight = corners[2];
}
}
}
我只想指出一点,具体取决于您的比例以及移动鼠标的速度,最终可能会出现点,这是因为,如果您移动鼠标的速度更快,此算法只会更新每帧鼠标移过的像素那么每帧有1 px的间隙,可以通过存储mousePosition的最后一帧,获得该帧的新位置,并创建一条线,然后更新该线上的所有点来解决此问题。