Unity中实现从随机位置逐渐扩散的颜色渐变动画效果

效果 

         最近要做个产品展示的案例,突然想到之前看到的一个汽车商业案例,点击不同的颜色车漆很顺滑的过渡到目标颜色,非常炫酷,于是就想着实现一下,废话不多说,先来看效果。

实现过程

        要实现这种效果肯定得整shader,我对shader是一窍不通,没办法只能去问chatgpt,给出了这样的代码;

Shader "Custom/GradientShader"
{
    Properties
    {
        _Center ("Center", Vector) = (0,0,0,0)
        _Color1 ("Color 1", Color) = (1,1,1,1)
        _Color2 ("Color 2", Color) = (0,0,0,1)
        _Radius ("Radius", Float) = 0.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        Pass
        {
            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;
            };

            float4 _Center;
            fixed4 _Color1;
            fixed4 _Color2;
            float _Radius;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float dist = distance(i.uv, _Center.xy);
                float t = smoothstep(0.0, 1.0, dist / _Radius);
                return lerp(_Color1, _Color2, t);
            }
            ENDCG
        }
    }
}

        控制的脚本如下;

using UnityEngine;

public class GradientAnimation : MonoBehaviour
{
    public Material material;
    public Color color1 = Color.white;
    public Color color2 = Color.black;
    public float duration = 5.0f;

    private Vector2 center;
    private float time;

    void Start()
    {
        // 随机生成起始位置
        center = new Vector2(Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f));
        material.SetVector("_Center", new Vector4(center.x, center.y, 0, 0));
        material.SetColor("_Color1", color1);
        material.SetColor("_Color2", color2);
        material.SetFloat("_Radius", 0.0f); // 初始半径为0
    }

    void Update()
    {
        time += Time.deltaTime;
        float radius = Mathf.Lerp(0.0f, 1.414f, time / duration); // 在duration时间内线性插值
        material.SetFloat("_Radius", radius);

        // 确保半径不会超过最大值
        if (time >= duration)
        {
            material.SetFloat("_Radius", 1.414f); // 最大半径sqrt(2) ≈ 1.414, 覆盖整个纹理
        }
    }
}

        我试了下,可以实现,但是效果不好。这个shader一些基本的像金属度啥的都没有,只是纯色,效果很一般,不是我想要的结果。

        没办法,接着查。我想着shader是不是可以像C#那样继承某个shader的特性,查了一下,不行,放弃。

        后来了解到可以通过shader graph很快创建一个shader,我就想是不是可以在shader graph里实现一个基础shader,再把代码里的内容转成shader graph里的元素加在一起不就可以了吗。正好在b站上看到一个基础shader的制作教程,说干就干。

        基础shader大家可以看这个视频:

2022版Unity Shader Graph教程01-1 Subgraph 超简单ShaderGraph入门

        接下来讲讲如何在shader graph里如何实现,基础的不讲了,自己看视频。

制作shader graph

添加属性

先添加四个属性;我这里还添加了个NoiseScale,用于控制噪声的缩放。

获取UV坐标

创建一个“UV”节点,用来获取纹理坐标;

计算距离

创建一个Subtract节点,将UV节点的输出连接到Subtract节点的A输入。

Blackboard上将Center属性拖到节点编辑器中,连接到Subtract节点的B输入。

创建一个Length节点,将Subtract节点的输出连接到Length节点的输入。

添加噪声

创建一个Simple Noise节点,用于生成噪声纹理。

创建一个Multiply节点,将Length节点的输出连接到Multiply节点的A输入。

Blackboard上将NoiseScale属性拖到节点编辑器中,连接到Multiply节点的B输入。

Multiply节点的输出连接到Simple Noise节点的UV输入。

混合距离和噪声

创建一个Add节点,将Length节点的输出连接到Add节点的A输入。

Simple Noise节点的输出连接到Add节点的B输入。

创建一个Divide节点,将Add节点的输出连接到Divide节点的A输入。

Blackboard上将Radius属性拖到节点编辑器中,连接到Divide节点的B输入。

创建一个Smoothstep节点,将Divide节点的输出连接到Smoothstep节点的In输入。

创建一个Lerp节点,在Blackboard上将MainColor和TargetColor属性分别拖到节点编辑器中,连接到Lerp节点的AB输入。

Smoothstep节点的输出连接到Lerp节点的T输入。

连接输出

Lerp节点的输出连接到PBR Master节点的Base Color输入。

总结

shader graph大家按这个流程基本上能搞定的,如果实在搞不定我这边也上传上去了,可以在这个地址下载:Unity中从随机位置逐渐扩散的颜色渐变动画效果的shaderGraph

脚本控制渐变

接下来就简单了,脚本控制Radius就能实现渐变效果呢,这里贴上关键代码,具体怎么实现各位自用发挥吧。

using System.Collections.Generic;
using UnityEngine;

public class Vehicle : MonoBehaviour
{
    [SerializeField] private List<MeshRenderer> shells;
    [SerializeField] private float radiusMax = 5f;
    [SerializeField] private float duration = 4f;

    private bool changeColor = false;
    private float timer = 0;

    [SerializeField]private Color currentColor;

    private void Start()
    {
        for (int i = 0; i < shells.Count; i++)
        {
            shells[i].material.SetColor("_MainColor", currentColor);
        }
    }

    private void Update()
    {
        if (changeColor)
        {
            timer += Time.deltaTime;
            float radius = Mathf.Lerp(0.0f,radiusMax,timer/duration);

            for (int i = 0; i < shells.Count; i++)
            {
                shells[i].material.SetFloat("_Radius", radius);
            }

            if (radius>=radiusMax)
            {
                timer = 0;
                changeColor = false;
            }
        }
    }

    /// <summary>
    /// 改变颜色
    /// </summary>
    /// <param name="color"></param>
    public void ChangeColor(Color color)
    {
        if (changeColor) return;

        for (int i = 0; i < shells.Count; i++)
        {
            Vector2 center = new Vector2(Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f));
            shells[i].material.SetVector("_Center", new Vector4(center.x, center.y, 0, 0));
            shells[i].material.SetColor("_MainColor", currentColor);
            shells[i].material.SetColor("_TargetColor", color);
            shells[i].material.SetFloat("_Radius", 0.0f);
        }

        currentColor = color;
        changeColor = true;
    }
}

ok!效果是实现了,但是跟我当时看到的那个效果还是有差距的,可惜找不到那个案例了,以后有时间再优化吧,就这样吧!有用的话一键三连吧!

转载请注明出处

Unity中实现从随机位置逐渐扩散的颜色渐变动画效果-CSDN博客Unity中实现从随机位置逐渐扩散的颜色渐变动画效果https://blog.csdn.net/enjoySoledad/article/details/140532465?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22140532465%22%2C%22source%22%3A%22enjoySoledad%22%7D

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值