Unity取色器实现

这篇具有很好参考价值的文章主要介绍了Unity取色器实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  1. Unity编辑器的取色器很好用,但是如何在项目中使用,这就难倒了我,查查找找,终于完成了功能。于是在这里简单记录一下。

一、简单介绍

取色器中根据选取颜色自动调整色轮位置的实现方法,unity,游戏引擎

演示

如上所示,一个简单的取色功能,加上一个反向定位取色板功能

二、原理

首先通过一个色环图片,获取到色环上的基础颜色,再通过分辨率,对内部色盘进行HSV转化,最后通过内部色盘获取最终颜色

三、实现

1、取色

  1. 通过鼠标的点击、拖拽更新色环所需要的颜色
	public void OnPointerDown(PointerEventData eventData)
    {
        CircleMove(eventData);
    }


    public void OnDrag(PointerEventData eventData)
    {
        CircleMove(eventData);
    }
     public void CircleMove(PointerEventData eventData)
    {

        //计算选色环的位置
        //Vector2 o = new Vector2(Screen.width / 1920f * m_ColorWheel.rectTransform.rect.width / 2, Screen.height / 1080f * m_ColorWheel.rectTransform.rect.height / 2);
        Vector2 o = new Vector2(m_ColorWheel.rectTransform.rect.width / 2, m_ColorWheel.rectTransform.rect.height / 2);
        float r = m_ColorWheel.rectTransform.rect.width / 2 - m_SelectorWheel.rect.width / 2;

        //鼠标位置 - 圆形位置 = 圆心指向鼠标位置的向量
        Vector3 mousepos = transform.parent.InverseTransformPoint(eventData.position) -
                           transform.parent.InverseTransformPoint(transform.position + (Vector3)o);
        Vector3 rightPos = transform.parent.InverseTransformVector(m_ColorWheel.rectTransform.right);

        o = new Vector2(m_ColorWheel.rectTransform.rect.width / 2, m_ColorWheel.rectTransform.rect.height / 2);
        angle = VectorAngle(mousepos, rightPos);
        newV2.x = o.x + r * Mathf.Cos(angle * Mathf.Deg2Rad);
        newV2.y = o.y + r * Mathf.Sin(angle * Mathf.Deg2Rad);
        m_SelectorWheel.localPosition = newV2;

        //获取调色板图片
        Texture2D tex = m_ColorWheel.sprite.texture;
        //1.计算选色环在Image上的位置占比 (0~1)
        //2.通过位置占比,映射获取到要获取的贴图像素位置
        int x = (int)(m_SelectorWheel.localPosition.x / m_ColorWheel.rectTransform.rect.width * tex.width);
        int y = (int)(m_SelectorWheel.localPosition.y / m_ColorWheel.rectTransform.rect.height * tex.height);
        //通过Texture2D.GetPixel这个方法来获取该位置下的像素的颜色值
        Color color = tex.GetPixel(x,y);        RGBToHSV(color);
        UpdateSaturation(currentColorHSV);
        m_SubColorSelector.UpdateColor(eventData);
        
    }
    float VectorAngle(Vector2 from, Vector2 to)
    {
        float angle;
        Vector3 cross=Vector3.Cross(from, to);
        angle = Vector2.Angle(from, to);
        return cross.z > 0 ? -angle : angle;
    }
  1. 通过色环的颜色转化成HSV
    private void UpdateSaturation(Vector4 hsv)
    {
        for (int y = 0; y < piexlHeight; y++)
        {
            for (int x = 0; x < piexlWidth; x++)
            {
                Color pixColor = GetSaturation(hsv, x / piexlWidth, y / piexlHeight);
                saturationTexture2D.SetPixel(x, y, pixColor);
            }
        }

        saturationTexture2D.Apply();
        m_ColorSaturation.texture = saturationTexture2D;
    }
    private Color GetSaturation(Vector4 hsv, float x, float y)
    {
        Vector4 saturationHSV = hsv;
        saturationHSV.y = x;
        saturationHSV.z = y;
        saturationHSV.w = 1;
        return HSVToRGB(saturationHSV);
    }
    private Color HSVToRGB(Vector4 hsv)
    {
        Color color = Color.HSVToRGB(hsv.x, hsv.y, hsv.z);
        color.a = hsv.w;
        return color;
    }
  1. 通过鼠标的点击、拖拽更新内部色盘最终选择出来的颜色
	public void OnPointerDown(PointerEventData eventData)
    {
        OnDrag(eventData);
    }
    

    public void OnDrag(PointerEventData eventData)
    {

        //需要将背景调色板的中心点改为左下角(0,0)
        //PointerEventData.position返回的是当前指针的位置,左下角为原点(0,0),右上角(屏幕宽,屏幕高),根据分辨率来算
        Vector3 selectorWheelPos = transform.InverseTransformPoint(eventData.position);
        
        selectorWheelPos.x = Mathf.Clamp(selectorWheelPos.x,0,m_ColorPickPanel.rectTransform.rect.width - 1);
        selectorWheelPos.y = Mathf.Clamp(selectorWheelPos.y,0,m_ColorPickPanel.rectTransform.rect.height - 1);
        m_SelectorWheel.localPosition = selectorWheelPos;

        //获取调色板图片
        Texture2D tex = (Texture2D)m_ColorPickPanel.texture;
        //获取鼠标(smallIcon)在调色板上的x,y轴上的比例
        float xtemp = m_SelectorWheel.localPosition.x / m_ColorPickPanel.rectTransform.rect.width;
        float ytemp = m_SelectorWheel.localPosition.y / m_ColorPickPanel.rectTransform.rect.height;
        
        //设置圆圈颜色分类
        if (ytemp <= 0.5f || xtemp >= 0.5f) m_SelectorWheelImage.color = Color.white;
        else m_SelectorWheelImage.color = Color.black;
        
        //通过鼠标在调色板的位置比例,获取鼠标在调色板上的具体(X,Y)坐标
        int x = (int)(xtemp * tex.width);
        int y = (int)(ytemp * tex.height);

        //通过Texture2D.GetPixel这个方法来获取该位置下的像素的颜色值
        Color color = tex.GetPixel(x, y);
        //设置颜色
        FinalColor = color;
        ColorPlate.color = FinalColor;
    }

2、根据颜色设置取色器

  1. 根据颜色计算HSV
Color.RGBToHSV(color, out float hue, out float saturation, out float brightness);
  1. 计算色环的选取位置
 		//获取内部色盘的最亮色
        RGBToHSV(Color.HSVToRGB(hue, 1, 1));
        //计算色环小圈的位置
        Vector2 o = new Vector2(m_ColorWheel.rectTransform.rect.width / 2, m_ColorWheel.rectTransform.rect.height / 2);
        float r = m_ColorWheel.rectTransform.rect.width / 2 - m_SelectorWheel.rect.width / 2;
        newV2.x = o.x + r * Mathf.Cos(hue*360 * Mathf.Deg2Rad);
        newV2.y = o.y + r * Mathf.Sin(hue*360 * Mathf.Deg2Rad);
        m_SelectorWheel.localPosition = newV2;
  1. 更新内部色盘图片
    private void UpdateSaturation(Vector4 hsv)
    {
        for (int y = 0; y < piexlHeight; y++)
        {
            for (int x = 0; x < piexlWidth; x++)
            {
                Color pixColor = GetSaturation(hsv, x / piexlWidth, y / piexlHeight);
                saturationTexture2D.SetPixel(x, y, pixColor);
            }
        }

        saturationTexture2D.Apply();
        m_ColorSaturation.texture = saturationTexture2D;
    }
  1. 计算内部色盘选取位置

        //计算内部色盘小圈位置
        m_SubColorSelector.m_SelectorWheel.transform.localPosition = new Vector2(saturation * m_SubColorSelector.RectTransform.rect.width, brightness * m_SubColorSelector.RectTransform.rect.height);

四、完整代码

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

public class ColorSelector : MonoBehaviour,  IPointerDownHandler, IDragHandler
{

    public SubColorSelector m_SubColorSelector;
    //色环
    public Image m_ColorWheel;
    //调色板
    public RawImage m_ColorSaturation;
    //选择图标
    public RectTransform m_SelectorWheel;
    
    //调色板图片
    private Texture2D saturationTexture2D;

    private readonly float piexlWidth = 256.0f;
    private readonly float piexlHeight = 256.0f;
    private readonly float huePiexWidth = 50.0f;
    //当前HSV
    private Vector4 currentColorHSV = new Vector4(0, 1, 1, 1);
    

    void Awake()
    {
        saturationTexture2D = new Texture2D((int)piexlWidth, (int)piexlHeight);
        m_ColorSaturation.texture = saturationTexture2D;
    }
    
    void Start()
    {
        Init();
    }
    public void SetSelectorWheel(Image Ima)
    {
        //计算传入颜色的HSV
        Color.RGBToHSV(Ima.color, out float hue, out float saturation, out float brightness);
        //获取内部色盘的最亮色
        RGBToHSV(Color.HSVToRGB(hue, 1, 1));
        //计算色环小圈的位置
        Vector2 o = new Vector2(m_ColorWheel.rectTransform.rect.width / 2, m_ColorWheel.rectTransform.rect.height / 2);
        float r = m_ColorWheel.rectTransform.rect.width / 2 - m_SelectorWheel.rect.width / 2;
        newV2.x = o.x + r * Mathf.Cos(hue*360 * Mathf.Deg2Rad);
        newV2.y = o.y + r * Mathf.Sin(hue*360 * Mathf.Deg2Rad);
        m_SelectorWheel.localPosition = newV2;
        //更新内部色盘图片
        UpdateSaturation(currentColorHSV);
        //计算内部色盘小圈位置
        m_SubColorSelector.m_SelectorWheel.transform.localPosition = new Vector2(saturation * m_SubColorSelector.RectTrans.rect.width, brightness * m_SubColorSelector.RectTrans.rect.height);

        m_SubColorSelector.ColorPlate.color = Ima.color;
    }
    public void Init()
    {
        //计算选色环的位置
        Vector2 o = new Vector2(m_ColorWheel.rectTransform.rect.width / 2, m_ColorWheel.rectTransform.rect.height / 2);
        float r = m_ColorWheel.rectTransform.rect.width / 2 - m_SelectorWheel.rect.width / 2;

        //鼠标位置 - 圆形位置 = 圆心指向鼠标位置的向量
        Vector3 mousepos = transform.parent.InverseTransformPoint(m_SelectorWheel.position) -
                           transform.parent.InverseTransformPoint(transform.position + (Vector3)o);
        Vector3 rightPos = transform.parent.InverseTransformVector(m_ColorWheel.rectTransform.right);

        angle = VectorAngle(mousepos, rightPos);
        newV2.x = o.x + r * Mathf.Cos(angle * Mathf.Deg2Rad);
        newV2.y = o.y + r * Mathf.Sin(angle * Mathf.Deg2Rad);
        m_SelectorWheel.localPosition = newV2;

        //获取调色板图片
        Texture2D tex = m_ColorWheel.sprite.texture;
        //1.计算选色环在Image上的位置占比 (0~1)
        //2.通过位置占比,映射获取到要获取的贴图像素位置
        int x = (int)(m_SelectorWheel.localPosition.x / m_ColorWheel.rectTransform.rect.width * tex.width);
        int y = (int)(m_SelectorWheel.localPosition.y / m_ColorWheel.rectTransform.rect.height * tex.height);
        //通过Texture2D.GetPixel这个方法来获取该位置下的像素的颜色值
        Color color = tex.GetPixel(x, y);
        RGBToHSV(color);
        UpdateSaturation(currentColorHSV);
        m_SubColorSelector.UpdateColor();
    }

    /// <summary>
    /// 更新调色板
    /// </summary>
    /// <param name="hsv"></param>
    private void UpdateSaturation(Vector4 hsv)
    {
        for (int y = 0; y < piexlHeight; y++)
        {
            for (int x = 0; x < piexlWidth; x++)
            {
                Color pixColor = GetSaturation(hsv, x / piexlWidth, y / piexlHeight);
                saturationTexture2D.SetPixel(x, y, pixColor);
            }
        }

        saturationTexture2D.Apply();
        m_ColorSaturation.texture = saturationTexture2D;
    }

    /// <summary>
    /// 根据设置分辨率转化HSV
    /// </summary>
    /// <param name="hsv"></param>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    private Color GetSaturation(Vector4 hsv, float x, float y)
    {
        Vector4 saturationHSV = hsv;
        saturationHSV.y = x;
        saturationHSV.z = y;
        saturationHSV.w = 1;
        return HSVToRGB(saturationHSV);
    }

    private Color HSVToRGB(Vector4 hsv)
    {
        Color color = Color.HSVToRGB(hsv.x, hsv.y, hsv.z);
        color.a = hsv.w;
        return color;
    }

    private void RGBToHSV(Color color)
    {
        Color.RGBToHSV(color, out currentColorHSV.x, out currentColorHSV.y, out currentColorHSV.z);
        // 更新调色板的位置
    }

    

    public void OnPointerDown(PointerEventData eventData)
    {
        CircleMove(eventData);
    }


    public void OnDrag(PointerEventData eventData)
    {
        CircleMove(eventData);
    }

    public float angle;
    private Vector2 newV2 =  Vector2.zero;
    
    public void CircleMove(PointerEventData eventData)
    {

        //计算选色环的位置
        //Vector2 o = new Vector2(Screen.width / 1920f * m_ColorWheel.rectTransform.rect.width / 2, Screen.height / 1080f * m_ColorWheel.rectTransform.rect.height / 2);
        Vector2 o = new Vector2(m_ColorWheel.rectTransform.rect.width / 2, m_ColorWheel.rectTransform.rect.height / 2);
        float r = m_ColorWheel.rectTransform.rect.width / 2 - m_SelectorWheel.rect.width / 2;

        //鼠标位置 - 圆形位置 = 圆心指向鼠标位置的向量
        Vector3 mousepos = transform.parent.InverseTransformPoint(eventData.position) -
                           transform.parent.InverseTransformPoint(transform.position + (Vector3)o);
        Vector3 rightPos = transform.parent.InverseTransformVector(m_ColorWheel.rectTransform.right);

        o = new Vector2(m_ColorWheel.rectTransform.rect.width / 2, m_ColorWheel.rectTransform.rect.height / 2);
        angle = VectorAngle(mousepos, rightPos);
        newV2.x = o.x + r * Mathf.Cos(angle * Mathf.Deg2Rad);
        newV2.y = o.y + r * Mathf.Sin(angle * Mathf.Deg2Rad);
        m_SelectorWheel.localPosition = newV2;

        //获取调色板图片
        Texture2D tex = m_ColorWheel.sprite.texture;
        //1.计算选色环在Image上的位置占比 (0~1)
        //2.通过位置占比,映射获取到要获取的贴图像素位置
        int x = (int)(m_SelectorWheel.localPosition.x / m_ColorWheel.rectTransform.rect.width * tex.width);
        int y = (int)(m_SelectorWheel.localPosition.y / m_ColorWheel.rectTransform.rect.height * tex.height);
        //通过Texture2D.GetPixel这个方法来获取该位置下的像素的颜色值
        //Debug.Log(m_SelectorWheel.localPosition + "!!!!!!!!!!!!!!!!");
        Color color = tex.GetPixel(x,y);
        //Debug.Log("+++++++图片中当前像素的颜色值:" + color);
        RGBToHSV(color);
        UpdateSaturation(currentColorHSV);
        m_SubColorSelector.UpdateColor(eventData);
        
    }
    
    float VectorAngle(Vector2 from, Vector2 to)
    {
        float angle;
        Vector3 cross=Vector3.Cross(from, to);
        angle = Vector2.Angle(from, to);
        return cross.z > 0 ? -angle : angle;
    }
}


using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class SubColorSelector : MonoBehaviour,  IPointerDownHandler, IDragHandler
{

    //显示板
    public Image ColorPlate;
    //最终颜色
    public Color FinalColor;
    //调色板
    public RawImage m_ColorPickPanel;
    //选择图标
    public RectTransform m_SelectorWheel;
    public RectTransform RectTrans;

    private RawImage m_SelectorWheelImage;
    //记录之前的位置
    Vector3 oldposition;


    void Awake()
    {
        RectTrans = transform as RectTransform;
        oldposition = m_SelectorWheel.position;
        m_SelectorWheelImage = m_SelectorWheel.GetComponent<RawImage>();
    }

    

    public void OnPointerDown(PointerEventData eventData)
    {
        OnDrag(eventData);
    }
    

    public void OnDrag(PointerEventData eventData)
    {

        //需要将背景调色板的中心点改为左下角(0,0)
        //PointerEventData.position返回的是当前指针的位置,左下角为原点(0,0),右上角(屏幕宽,屏幕高),根据分辨率来算
        Vector3 selectorWheelPos = transform.InverseTransformPoint(eventData.position);
        
        selectorWheelPos.x = Mathf.Clamp(selectorWheelPos.x,0,m_ColorPickPanel.rectTransform.rect.width - 1);
        selectorWheelPos.y = Mathf.Clamp(selectorWheelPos.y,0,m_ColorPickPanel.rectTransform.rect.height - 1);
        m_SelectorWheel.localPosition = selectorWheelPos;

        //获取调色板图片
        Texture2D tex = (Texture2D)m_ColorPickPanel.texture;
        //获取鼠标(smallIcon)在调色板上的x,y轴上的比例
        float xtemp = m_SelectorWheel.localPosition.x / m_ColorPickPanel.rectTransform.rect.width;
        float ytemp = m_SelectorWheel.localPosition.y / m_ColorPickPanel.rectTransform.rect.height;
        
        //设置圆圈颜色分类
        if (ytemp <= 0.5f || xtemp >= 0.5f) m_SelectorWheelImage.color = Color.white;
        else m_SelectorWheelImage.color = Color.black;
        
        //通过鼠标在调色板的位置比例,获取鼠标在调色板上的具体(X,Y)坐标
        int x = (int)(xtemp * tex.width);
        int y = (int)(ytemp * tex.height);

        //通过Texture2D.GetPixel这个方法来获取该位置下的像素的颜色值
        Color color = tex.GetPixel(x, y);
        //设置颜色
        FinalColor = color;
        ColorPlate.color = FinalColor;
    }

    /// <summary>
    /// 更新颜色
    /// </summary>
    /// <param name="eventData"></param>
    public void UpdateColor(PointerEventData eventData = null)
    {
        //获取调色板图片
        Texture2D tex = (Texture2D)m_ColorPickPanel.texture;
        float xtemp = m_SelectorWheel.localPosition.x / m_ColorPickPanel.rectTransform.rect.width;
        float ytemp = m_SelectorWheel.localPosition.y / m_ColorPickPanel.rectTransform.rect.height;
        int x = (int)(xtemp * tex.width);
        int y = (int)(ytemp * tex.height);
        Color color = tex.GetPixel(x, y);
        FinalColor = color;
        ColorPlate.color = FinalColor;
    }
}

五、示例资源

后续更新

已更新
示例场景文章来源地址https://www.toymoban.com/news/detail-775437.html

到了这里,关于Unity取色器实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity使用着色器实现颜色渐变

    效果演示: 当前效果需要自己手动写一个shader,效果与unity版本无关,模型没有特别要求 在unity创建一个SurfaceShader类型的shader,命名为CotrolGradient_3Color,双击进入vs进行编辑,shader内容如下:

    2024年02月11日
    浏览(41)
  • unity学习(33)——角色选取界面(原版)

    10ARPG网络游戏编程实践(十):角色选择UI及创建面板制作(一)(流畅)_哔哩哔哩_bilibili 角色选择 界面教程中是这样的!(这个美工肯定是不能拿出去卖的,但是是有学习价值的) 角色创建 界面大概是这样的:   视频就是在水时间,时至今日做这种界面已无难度,明天

    2024年02月21日
    浏览(52)
  • opencv图片根据规则改变颜色

    1. 读入图片 2.通道分离 3.像素值在【100,200】之间,赋值128。大于200赋值255,小于100赋值0。 原图如下。 处理后的图片,缺口变得清晰。  

    2024年02月15日
    浏览(45)
  • Excel根据颜色求和与计数

    一、需求 一个Excel中有不同颜色标记的单元格,统计的时候,需要按照颜色进行统计。 人工来做肯定是不可能了,借助Excel的功能好像也没有思路,其实这种情况可以通过使用vba自定义函数来实现。 二、实现方法 1.代码 根据颜色求和函数代码 根据颜色计数函数代码 在这里我

    2024年02月09日
    浏览(30)
  • Unity绘画功能实现(包含涂鸦、颜色一键填充、撤销操作、保存图像)

    项目需要,要实现在图像上进行绘画,看来网上的很多Unity绘画代码,感觉挺复杂的而且功能不全,这里我自己实现了一个在图像上进行绘画的代码,包含了涂鸦、一键填充颜色、撤销上一次操作、保存图片功能。 本项目是在http://www.qb5200.com/article/391439.html上进行了魔改。 左

    2024年02月14日
    浏览(43)
  • Unity实用功能之UGUI的Text实现颜色渐变详解 Unity3D

    在Unity3D中,UGUI是一种用于创建用户界面的强大工具。其中的Text组件用于显示文本内容,而通过实现颜色渐变效果,可以使文本更加生动和吸引人。本文将详细介绍如何在Unity中使用UGUI的Text组件实现颜色渐变效果,并提供相应的源代码。 首先,我们需要创建一个空的GameObj

    2024年02月02日
    浏览(57)
  • Unity2021 实现不同面颜色不同的立方体鼠标键盘控制旋转

    1.创建一个3D的项目 2.创建一个Cube和一个Plane(其实没啥用,可以不建) 3.在Project的Assets中创建三个文件夹,后续放代码文件 4.设置颜色。 (1)在Material文件夹中右键创建一个Material文件命名为CubeMaterial,也就是下图中第一个白色的圆圈。中间的是控制Plane的,如果没有创建

    2024年02月08日
    浏览(45)
  • uniapp:如何将返回标根据下滑的距离而改变颜色

    在项目过程中我们会遇到这种情况: 返回标和背景颜色重合导致无法看见的情况,这里有一个简单的方法可以实现 这个api会 实时监听你鼠标向下滚动的距离 ,直接写在vue2:methods中即可。vue3直接写在setup函数中就可以了如图所示: 来看看运行效果:

    2024年01月22日
    浏览(45)
  • WEBGL(4):动态绘制点并根据详细自定义颜色

    1 实现代码 2 实现效果 根据鼠标点击的坐标,实现方块颜色进行变化

    2024年02月10日
    浏览(42)
  • 根据若依系统+minio实现批量下载附件并自动压缩成zip

    效果实现:   分割!!!! 以下代码参考于 http://t.csdn.cn/4dUmDwg 话不多说 直接从后端开始 0.首先是pom依赖 1.后端Controller ids和tableName为我业务需要(主要是查询数据库的附件表) 2.Service实现层 需要各位自己搜索minio关于下载的代码 也就是获取图片的inputStream流(因为各自代码逻辑不同

    2024年02月09日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包