涂色功能

先上效果图,红色部分为涂色:

场景节点

绘制节点

// 挂在UICamera上
public class UIManager : MonoBehaviour {

    public static UIManager Instance;
    public Camera camera;
    public Canvas canvas;

	void Awake () {
        Instance = this;
        camera = GetComponent<Camera>();
        canvas = camera.transform.GetChild(0).GetComponent<Canvas>();
	}
	
}

涂色类:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class DrawItem : MonoBehaviour {

    public Color drawColor = Color.red; // 绘画颜色

    private RawImage drawImage; // Image的Texture是只读的,如果要进行操作则用RawImage
    private Texture2D drawTexture;  // 绘制的材质

    private Vector3 preMouseClickPos;
    private bool isDrawing;

    private Canvas canvas;
    private Vector2 canvasSize;

	void Start () {
        drawImage = GetComponent<RawImage>();
        drawTexture = Instantiate(drawImage.mainTexture) as Texture2D;    // 绘制的材质,需要新建一个,避免影响原来的图片,注意类型为2D
        drawImage.texture = drawTexture;
        isDrawing = false;

        canvas = UIManager.Instance.canvas;
        canvasSize = canvas.GetComponent<CanvasScaler>().referenceResolution;
	}
	
	void Update () {
            // 鼠标点击
        if (Input.GetMouseButtonDown(0))
        {
            // EventSystem是UI的事件系统,所以IsPointerOverGameObject中的GameObject是针对UI的,而不是普遍意义上的GameObject
            if (EventSystem.current.IsPointerOverGameObject())
            {
                isDrawing = true;
                preMouseClickPos = Input.mousePosition;
                //Debug.Log("preMouseClickPos=" + preMouseClickPos);
                Draw(Input.mousePosition);
            }
        }
        else if (Input.GetMouseButton(0))
        {
            if (isDrawing && preMouseClickPos != Input.mousePosition)
            {
                Draw(Input.mousePosition);
                //LerpDraw(Input.mousePosition);
                preMouseClickPos = Input.mousePosition;
            }
        }
        else if (Input.GetMouseButtonUp(0))
        {
            if (EventSystem.current.IsPointerOverGameObject())
            {
                isDrawing = false;
            }
        }
		
	}

    private void Draw(Vector2 mousePos2D)
    {
        //Debug.Log("绘画");
            // 将鼠标位置转换为在绘制材质的坐标
        Vector2 clickTexturePos;
        //Vector2 mousePos2D = Input.mousePosition;
        Vector2 textureSize = new Vector2(drawTexture.width, drawTexture.height);
        RectTransform rectTran = transform as RectTransform;

            // 获取绘制材质在uicamera的屏幕坐标
        Vector2 textureCameraPos = RectTransformUtility.WorldToScreenPoint(UIManager.Instance.camera, rectTran.position);
            // 当前绘制材质左下角第一个点的实际屏幕坐标
        Vector2 firsePointPos = textureCameraPos - textureSize / 2;   // 默认RectTransform的Anchors和Pivot参数都为0.5
            // 鼠标在绘制材质的坐标
        clickTexturePos = mousePos2D - firsePointPos;


        //float preAlpha;
            // 遍历材质的像素,并进行涂色
        for (int x = 0; x < drawTexture.width; x++)
        {
            for (int y = 0; y < drawTexture.height; y++)
            {
                if (Vector2.Distance(new Vector2(x, y), clickTexturePos) < 10)  // 在一定距离内的都涂上颜色
                {
                    //preAlpha = drawTexture.GetPixel(x, y).a;
                    //drawColor.a = preAlpha;   // 透明度不变
                    drawTexture.SetPixel(x, y, drawColor);
                }
            }
        }
        drawTexture.Apply();    // 修改完后需要应用才能生效
    }


        // 差值涂色,可以避免鼠标拖动过快,涂色不连续的问题。但是拖动越快越卡
        // 在两次涂色中间插值涂色
    Vector2 _lastPoint = Vector2.zero;
    float _brushLerpSize = 10;
    private void LerpDraw(Vector2 point)
    {
        Draw(point);

        if (_lastPoint == Vector2.zero)
        {
            _lastPoint = point;
            return;
        }

        float dis = Vector2.Distance(point, _lastPoint);
        if (dis > _brushLerpSize)
        {
            Vector2 dir = (point - _lastPoint).normalized;
            int num = (int)(dis / _brushLerpSize);
            for (int i = 0; i < num; i++)
            {
                Vector2 newPoint = _lastPoint + dir * (i + 1) * _brushLerpSize;
                Draw(newPoint);
            }
        }
        _lastPoint = point;
    }
}

材质类型为Sprite,属性必须选择可读写

IsPointerOverGameObject函数,兼容安卓端使用:

if (Input.GetMouseButtonDown(0) || (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began))
        {
#if UNITY_ANDROID && !UNITY_EDITOR
			if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
#else
            if (EventSystem.current.IsPointerOverGameObject())
#endif
                Debug.Log("当前触摸在UI上");

            else
                Debug.Log("当前没有触摸在UI上");
        }

适配不同分辨率

其中Canvas节点的Canvas Scaler组件的UI Scale Mode为Scale With Screen Size

修改上面涂色方法里面的计算鼠标点击材质位置即可。

Vector2 clickTexturePos;
        Vector2 scaleFacor = new Vector2(Screen.width / referenceResolution.x, Screen.height / referenceResolution.y);  // 缩放系数,当前屏幕分辨率/解决方案的大小
        Vector2 textureSize = new Vector2(m_tex2D.width * scaleFacor.x, m_tex2D.height * scaleFacor.y);
        RectTransform rectTran = transform as RectTransform;

        // 获取绘制材质在uicamera的屏幕坐标
        Vector2 textureCameraPos = RectTransformUtility.WorldToScreenPoint(m_camera, rectTran.position);
        // 当前绘制材质左下角第一个点的实际屏幕坐标
        Vector2 firsePointPos = textureCameraPos - textureSize / 2;   // 默认RectTransform的Anchors和Pivot参数都为0.5

        // 鼠标点击位置在绘制材质的坐标
        clickTexturePos = mousePos2D - firsePointPos;
        clickTexturePos = new Vector2(clickTexturePos.x / scaleFacor.x, clickTexturePos.y / scaleFacor.y);

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值