推荐阅读
- CSDN主页
- GitHub开源地址
- Unity3D插件分享
- QQ群:398291828
- 小红书
- 小破站
大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。
一、前言
先来看一下效果图:
感觉这种效果超炫酷,就根据大佬的文章复现了一下。
并且详细补充了一下相机、Post、材质球和Shader的处理过程,接下俩就看一下如何实现吧。
二、正文
2-1、实现思路
将鼠标光标的位置传递给Shader中,根据当前像素到像素的距离去处理像素点的颜色值。
这个动作需要拆分分为背景 + 边框两部分使用 2 个 Pass 处理。
Background Pass 背景
fixed4 frag (v2f i) : SV_Target
{fixed4 col = tex2D(_MainTex, i.uv);float dis = distance(_MousePos.xy, i.vertex.xy);float4 addColor = _Color;addColor.a = saturate(smoothstep(_ColorRadius, 0, dis) - _ColorOffset * sign(col.a-0.1));addColor.a = addColor.a * col.a * _ColorPow;return addColor;
}
Border Pass 边框
fixed4 frag (v2f i) : SV_Target
{fixed4 col = tex2D(_BorderTex, i.uvBorder);float dis = distance(_MousePos.xy, i.vertexBorder.xy);col = col + sign(col.a) * smoothstep(_ColorRadius, 0, dis) * _Color * _BorderPow;return col;
}
2-2、Shader编写
在Unity中,右键新建一个Shader→Standard Surface Shader
:
Shader
的代码如下:
Shader "Custom/HoverBtn"
{Properties{_MainTex ("MainTex", 2D) = "white" {}_MousePos ("MousePos", Vector) = (0,0,0,0)_ColorRedius ("ColorRedius", float) = 40[HDR]_Color ("Color", Color) = (0,0,0,1)_ColorOffset ("ColorOffset", Range(0, 1)) = 0_ColorPow ("ColorPow", Range(0, 1)) = 0.5_BorderTex ("BorderTex", 2D) = "white" {}_BorderColorMul ("BorderColorPow", float) = 2}SubShader{Tags { "RenderType"="Transparent" "Queue"="Transparent"}Blend SrcAlpha OneMinusSrcAlpha// MainTexPass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);return o;}fixed4 frag (v2f i) : SV_Target{fixed4 col = tex2D(_MainTex, i.uv);return col;}ENDCG}// MainColorPass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;// 原图形状maskfloat4 vert : POSITION;float2 uv : TEXCOORD0;};struct v2f{float4 vertex : SV_POSITION;float2 uv : TEXCOORD0;float4 vert : TEXCOORD1;};fixed4 _MousePos;float4 _Color;float _ColorRedius;float _ColorOffset;float _ColorPow;sampler2D _MainTex;float4 _MainTex_ST;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.vert = UnityObjectToClipPos(v.vert);o.uv = TRANSFORM_TEX(v.uv, _MainTex);return o;}fixed4 frag (v2f i) : SV_Target{fixed4 col = tex2D(_MainTex, i.uv);float dis = distance(_MousePos.xy, i.vertex.xy);float4 addColor = _Color;addColor.a = saturate(smoothstep(_ColorRedius, 0, dis) - _ColorOffset * sign(col.a-0.1));addColor.a = addColor.a * col.a * _ColorPow;return addColor;}ENDCG}// Border ColorPass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertexBorder : POSITION;float2 uvBorder : TEXCOORD0;};struct v2f{float2 uvBorder : TEXCOORD0;float4 vertexBorder : SV_POSITION;};sampler2D _BorderTex;float4 _BorderTex_ST;fixed4 _MousePos;float _ColorRedius;fixed4 _Color;float _BorderColorMul;v2f vert (appdata v){v2f o;o.vertexBorder = UnityObjectToClipPos(v.vertexBorder);o.uvBorder = TRANSFORM_TEX(v.uvBorder, _BorderTex);return o;}fixed4 frag (v2f i) : SV_Target{fixed4 col = tex2D(_BorderTex, i.uvBorder);float dis = distance(_MousePos.xy, i.vertexBorder.xy);col = col + sign(col.a) * smoothstep(_ColorRedius, 0, dis) * _Color * _BorderColorMul;return col;}ENDCG}}
}
2-3、控制代码编写
新建个脚本,挂载在按钮上,响应鼠标的悬浮和点击事件:
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;public class HoverBtn : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{[SerializeField, ColorUsage(true, true)]private Color color = Color.white;[SerializeField]private int radius = 100;private float scaleFactor;private Material material;private Canvas canvas;Coroutine coroutine_hide;Coroutine coroutine_show;void Start(){canvas = GetComponentInParent<Canvas>();scaleFactor = canvas.scaleFactor;var image = GetComponent<Image>();material = new(image.material);image.material = material;material.SetColor("_Color", color);material.SetFloat("_ColorRadius", radius);material.SetFloat("_ScaleFactor", scaleFactor);}private void Update(){material.SetVector("_MousePos", Input.mousePosition);if (scaleFactor != canvas.scaleFactor){scaleFactor = canvas.scaleFactor;material.SetFloat("_ScaleFactor", scaleFactor);}}void IPointerDownHandler.OnPointerDown(PointerEventData eventData){if (null != coroutine_show){StopCoroutine(coroutine_show);}if (null != coroutine_hide){StopCoroutine(coroutine_hide);}coroutine_show = StartCoroutine(ChangeInnerColorStateAsync(0.3f, true));}private IEnumerator ChangeInnerColorStateAsync(float duration, bool show){#region Easestatic float inCubic(float t) => t * t * t;static float outCubic(float t) => inCubic(t - 1f) + 1f;#endregionfloat time = 0;float start = material.GetFloat("_ColorOffset");float end = show ? 0 : 0.98f; // 当 _ColorOffset = 0 显示内部颜色Func<float, float> ease = show ? outCubic : inCubic;while (time < duration){time += Time.deltaTime;var p = ease(time / duration);material.SetFloat("_ColorOffset", Mathf.Lerp(start, end, p));yield return null;}}void IPointerUpHandler.OnPointerUp(PointerEventData eventData){if (null != coroutine_hide){StopCoroutine(coroutine_hide);}coroutine_hide = StartCoroutine(HideInnerColorAsync());}private IEnumerator HideInnerColorAsync(){//等待ShowInnerColorAsync结束if (null != coroutine_show){yield return coroutine_show;}coroutine_hide = StartCoroutine(ChangeInnerColorStateAsync(0.1f, false));}
}
2-4、材质球、材质、相机设置、UI设置、Post设置
(1)新建个材质球,使用HoverBtn这个Shader:
参数设置如下:
主要注意ColorRedius和Color两个参数。
(2)材质
右键另存为到本地,一个是背景一个是边框
(3)UI搭建
一个GridLayoutGroup父节点:
按钮设置:
可以修改按钮的颜色:
(4)Canvas渲染模式
(5)相机设置
相机增加Post Volume和Post Layer组件:
Post插件需要导入,设置Layer层,不做赘述。
整体搭建如下:
2-5、运行结果
三、参考链接
1、UI动效 01
2、UGUI 实现超赞 Win10 日历悬停效果
四、后记
总结一下就是:
(1)编写Shader
(2)编写C#脚本响应鼠标事件,传递鼠标位置
(3)其他效果设置
(4)运行起来
如果觉得本篇文章有用别忘了点个关注,关注不迷路,持续分享更多Unity干货文章。
你的点赞就是对博主的支持,有问题记得留言:
博主主页有联系方式。
博主还有跟多宝藏文章等待你的发掘哦:
专栏 | 方向 | 简介 |
---|---|---|
Unity3D开发小游戏 | 小游戏开发教程 | 分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。 |
Unity3D从入门到进阶 | 入门 | 从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。 |
Unity3D之UGUI | UGUI | Unity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。 |
Unity3D之读取数据 | 文件读取 | 使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。 |
Unity3D之数据集合 | 数据集合 | 数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。 |
Unity3D之VR/AR(虚拟仿真)开发 | 虚拟仿真 | 总结博主工作常见的虚拟仿真需求进行案例讲解。 |
Unity3D之插件 | 插件 | 主要分享在Unity开发中用到的一些插件使用方法,插件介绍等 |
Unity3D之日常开发 | 日常记录 | 主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等 |
Unity3D之日常BUG | 日常记录 | 记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。 |