Unity极坐标Shader特效,以及使用Instanced Property实现相同材质不同参数

Unity极坐标特效

先看看效果

Unity极坐标Shader特效


有时候我们需要在场景中摆放一些热点,用户点击之后出现互动,当然实现这个功能的方法有很多,作为一名程序员,当然是要用最简单的实现。用shader程序化实现它。

啥是极坐标

极坐标,又称极座标系。它是一种表示平面直角坐标系中点的方法,其中每个点都由距离原点的距离和从原点到该点的线段与某条固定轴正半轴(通常为 θ=0)的夹角(逆时针为正)两个值确定。这两个值通常用 (r, θ) 表示,其中 r 表示距离, θ 表示方向角度,范围在 0 度到 360 度之间。极坐标系常用于描述圆形和对称图形,以及某些物理问题中更自然地描述旋转对称性。
像这种波从中间生成向往扩散的效果,如果使用平常的UV坐标系,是很难实现的,但是使用极坐标系那就很简单了。

极坐标的实现

Unity极坐标Shader特效,以及使用Instanced Property实现相同材质不同参数_第1张图片
以ASE为例,将UV转为极坐标,然后取一张简单的渐变纹理,最后乘以一个颜色输出即可。
下面介绍一下每个参数的意义:
Unity极坐标Shader特效,以及使用Instanced Property实现相同材质不同参数_第2张图片

参数暴漏如上图所示,其中:

参数 意义
MainColor 输出颜色,HDR色
Size 大小,0-1
Texture 一张特殊的纹理,请见下图
Interval 间隔,0-1, 0.5表示发光的部分和不发光的部分尺寸相同
Scale 有多少条波
Offset 波的运动 0-1
那张特殊的纹理图如下:
Unity极坐标Shader特效,以及使用Instanced Property实现相同材质不同参数_第3张图片

如何让不同的物体,使用相同的材质,但是却拥有不同的参数?

效果如下所示,两个物体,都使用了相同的材质,但是他们的播放速度可以各自调节:

Unity Instanced Property 演示

这主要是使用了Shader中的Instanced Property。
Instanced Property的简介,这是我直接问的chat-GPT:
实例化属性(Instanced Properties)是 Unity Shader 中的一个特殊类型的属性,它可以实现以下功能:

  1. 通过实例化属性,我们可以同时创建多个实例化对象,并为每个对象赋予不同的属性值。这意味着我们可以创建多个具有不同属性的对象,而无需为每个对象编写单独的 Shader。

  2. 实例化属性还可以用于实现高效的绘制技术,例如 GPU 实例化(GPU Instancing)。在 GPU 实例化中,我们可以在一个 Draw Call 中一次性渲染大量的实例化对象,从而减少 CPU 和 GPU 的工作负载,提高渲染性能。

  3. 实例化属性还可以用于在 Unity Editor 中动态调整模型的属性,而无需重新编译 Shader。在 Unity Editor 中,我们可以直接调整每个实例的属性值,从而快速预览 Shader 在不同模型上的效果。

总的来说,实例化属性是 Unity Shader 中一种非常有用的功能,可以帮助我们实现更高效、更灵活的渲染技术。

在代码中修改Instanced Property主要使用Renderer类的SetPropertyBlock方法。代码如下:

using UnityEngine;
using Random = UnityEngine.Random;

public class WaveHotPoint : MonoBehaviour
{
    [SerializeField] private float Speed;
    private Renderer _renderer;
    private MaterialPropertyBlock propBlock;
    private float offset;
    private static readonly int OffsetIndex = Shader.PropertyToID("_Offset");

    private void Awake()
    {
        _renderer = GetComponent<SpriteRenderer>();
        propBlock = new MaterialPropertyBlock();
        _renderer.GetPropertyBlock(propBlock);

        offset = Random.value;
    }

    private void Update()
    {
        offset = (offset - Speed * Time.deltaTime) % 1f;
        propBlock.SetFloat(OffsetIndex, offset);
        _renderer.SetPropertyBlock(propBlock);
    }
}

但是要注意的是:UGUI中无法使用Instanced Property,因为UGUI中的CanvasRenderer类并没有SetPropertyBlock方法。问了chat-GPT,给出的方法是调用材质类的SetPropertyBlock方法,然而材质类并没有这个方法,不知道如何解决。如果您知道,麻烦评论区说一下,感谢!!!

你可能感兴趣的:(unity,材质,Shader,极坐标,特效)