Unity3D 颜色选择器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/caozhaodan/article/details/82868723

我们使用Unity或者其他软件都有一个颜色选择功能,但是这个组件只能在编辑模式中用。因此我就自己开发了一个颜色选择器的插件。

在网上也看到其他人的实现方法,都大同小异,通过新建一张texture,再用代码在图片上渲染颜色。正好我刚刚学习了Shader Forge,所以就想着用shader来渲染颜色,也可以复习新学到的知识。
开发环境:Unity2017.1.0f3 ShaderForge1.38

实现初效果
实现初效果

界面使用UGUI开发,选择器分为三个模块,Saturation,Hue,Color。

Hue是 七色渐变图,实现多种颜色的选择。
Saturation是Hue选择的颜色的饱和度。
Color是最后选择的颜色。

下面是每个功能的逐个实现。

首先用UGUI创建界面,可以全部使用Image
在这里插入图片描述
Saturation大小是80,轴点放到左上角。创建子节点SatDot,大小为5。
Hue高80,宽10,轴点放到最上方居中。创建子节点HueDot,高为3,宽为10。

ShaderForge创建2D shader,命名为HueShader,节点图如下
Hueshader
HueShader自带有Hue节点,直接使用即可。因为Hue是从上到下,所以UV只需要V点的区域。

ShaderForge创建2D shader,命名为SaturationShader,节点图如下
SaturationShader

因为需要在Hue上选择的颜色,只要将HueDot的y坐标相对Hue的高度的比例传给Value。

ShaderForge创建2D shader,命名为ColorShader,节点图如下
在这里插入图片描述

Value是HueDot位置相对Hue的高度的比例(同上),u是SatDot的x坐标相对于Saturation的宽度的比例,v是SatDot的y坐标相对于Saturation的高度的比例。

shader创建完成,在创建3个材质球,将3个shader分别拖到材质球,把材质球对应给不同的Image。
下面就开始一些简单的C#代码实现颜色的选择。

首先SatDot要在Saturation范围内通过鼠标拖动可以上下左右移动,HueDot要在Hue范围内只能上下移动,不能左右移动。
创建C#脚本,将脚本挂到SatDot和HueDot。如下代码即可使鼠标拖动SatDot和HueDot。

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

public class DragDot : MonoBehaviour,IDragHandler,IBeginDragHandler,IEndDragHandler
{
	public void OnDrag(PointerEventData eventData)
    {
		if(this.transform.parent.name=="Saturation"){
			Saturation (eventData.position);
		}else{
			Hue(eventData.position);
		}
    }
	public  void Saturation(Vector3 mousePos){
		this.transform.position = mousePos;
		if(this.transform.localPosition.x<0f){
			this.transform.localPosition = new Vector2 (0f, this.transform.localPosition.y);
		}
		if(this.transform.localPosition.x>80f){
			this.transform.localPosition = new Vector2 (80f, this.transform.localPosition.y);
		}
		if(this.transform.localPosition.y>0){
			this.transform.localPosition = new Vector2 (this.transform.localPosition.x,0);
		}
		if(this.transform.localPosition.y<-80f){
			this.transform.localPosition = new Vector2 (this.transform.localPosition.x,-80f);
		}
	}

	public void Hue(Vector3 mousePos){
		this.transform.position = new Vector2 (this.transform.position.x, mousePos.y);
		if(this.transform.localPosition.y>0){
			this.transform.localPosition = new Vector2 (this.transform.localPosition.x,0);
		}
		if(this.transform.localPosition.y<-80f){
			this.transform.localPosition = new Vector2 (this.transform.localPosition.x,-80f);
		}
	}
		
}

然后需要实现点击Saturation和Hue两个Image,两个Dot分别到点击的位置。
创建C#脚本,将脚本挂到Saturation和Hue。如下代码即可使SatDot和HueDot到鼠标点击位置。

using UnityEngine;
using UnityEngine.EventSystems;
public class ClickImage : MonoBehaviour ,IPointerClickHandler
{
	public DragPoint dragPoint;
	void IPointerClickHandler.OnPointerClick (PointerEventData eventData)
	{
		if(this.name=="Saturation"){
			dragPoint.Saturation (eventData.position);
		}else{
			dragPoint.Hue(eventData.position);
		}
	}
	

再新建一个脚本,可以使shader之间相互传值。

using UnityEngine;

public class ColorPicker : MonoBehaviour
{
	public Material satMat;
	public Material colorMat;
	
	public void GetHueColor(float hueValue){
		satMat.SetFloat ("_Value",hueValue);

	}

	public void GetSaturationColor(float x,float y,float hueValue){
		colorMat.SetFloat ("_Value",hueValue);
		colorMat.SetFloat ("_U",x);
		colorMat.SetFloat ("_V",y);
	}
}

最后,在DragDot 脚本中计算出拖动Dot时,Dot相对于父节点的比例,在调用GetHueColor方法和GetSaturationColor方法。

附上 完整的DragDot 的代码

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

public class DragPoint : MonoBehaviour,IDragHandler,IBeginDragHandler,IEndDragHandler
{
    public void OnDrag(PointerEventData eventData)
    {
		if(this.transform.parent.name=="Saturation"){
			Saturation (eventData.position);
		}else{
			Hue(eventData.position);
		}
    }

	public  void Saturation(Vector3 mousePos){

		if (this.name == "HueDot")
			return;

		this.transform.position = mousePos;
		if(this.transform.localPosition.x<0f){
			this.transform.localPosition = new Vector2 (0f, this.transform.localPosition.y);
		}
		if(this.transform.localPosition.x>80f){
			this.transform.localPosition = new Vector2 (80f, this.transform.localPosition.y);
		}
		if(this.transform.localPosition.y>0){
			this.transform.localPosition = new Vector2 (this.transform.localPosition.x,0);
		}
		if(this.transform.localPosition.y<-80f){
			this.transform.localPosition = new Vector2 (this.transform.localPosition.x,-80f);
		}

		float x = Mathf.Abs (this.transform.localPosition.x) / 80f;
		float y = Mathf.Abs (this.transform.localPosition.y) / 80f;
		//ColorPicker中创建单例
		//hueValue是在ColorPicker中初始换
		ColorPicker._instance.GetSaturationColor (x, y,ColorPicker._instance.hueValue);

	}

	public void Hue(Vector3 mousePos){
		this.transform.position = new Vector2 (this.transform.position.x, mousePos.y);
		if(this.transform.localPosition.y>0){
			this.transform.localPosition = new Vector2 (this.transform.localPosition.x,0);
		}
		if(this.transform.localPosition.y<-80f){
			this.transform.localPosition = new Vector2 (this.transform.localPosition.x,-80f);
		}
		
		float rate = (Mathf.Abs(this.transform.localPosition.y)  - 2) / 80f;
		ColorPicker._instance.hueValue = rate;
		ColorPicker._instance.GetHueColor (rate);
		GameObject dot = GameObject.Find ("SatDot");
		dot.GetComponent<DragPoint> ().Saturation (dot.transform.position);
	}
		
}

PC、安卓完美实现。还有一些其他功能,后续开发中…

展开阅读全文

没有更多推荐了,返回首页