学习笔记---Unity画线插件Vectrosity实现音频可视化的一个方法

Vectrosity插件的介绍

在Unity中使用这款插件可以绘制2d/3d/贝塞尔/圆/椭圆等线条图案。
使用步骤:
1.导入插件包,引入命名空间using Vectrosity
2.声明一个画线对象VectorLine line
3.在开始方法里实例化VectorLine对象:
在这里插入图片描述
4.设置位置坐标点到链表里去
5.调用line.Drwa()方法即可绘制所需线条图案
在这里插入图片描述

这是VectorLine类里的构造函数
其中name表示生成的线段的名字,points表示可以存放Vector2和Vector3类型的数据,用于在屏幕上绘制点,width表示生成线的宽度的像素值,texture表示线的材质,设为null表示默认材质,LineType有三个枚举是用来设置线条的类型的,Joins也有三个枚举是用来设置两条线段之间的过渡方式的。
在这里插入图片描述
在这里插入图片描述
其中continuous表示连续的,discrete表示离散的,points表示点的
Fill表示填充的,weld表示连接的,none表示没有连接的
在这里插入图片描述
编辑器运行时点击渲染组件会报错报错:
在这里插入图片描述
1、InvalidOperationException: This cannot be used during play mode.
2、ArgumentException: Getting control 7’s position in a group with only 7 controls when doing Repaint
3、ArgumentException: Getting control 7’s position in a group with only 7 controls when doing ScrollWheel
大致意思就是,运行时调整了实例化生成的线条组件,这个报错可以忽略。

Unity音频可视化的一个方法

利用音频的频谱率转化成线图的方式展现音频的波动效果。
简单实现:
1、Unity提供了AudioListener.GetSpectrumData可以直接获取音频的频谱。
语法:public void GetSpectrumData(float[] samples,int channel,FFTWindow window);
samples:
函数返回值。每个元素代表该音源当前在某个赫兹的强度。针对快速傅里叶变换算法的性能,数组大小必须为2的n次方,最小64,最大8192。
channel:
一般设置为0。该参数与硬件是mono或是stereo有关,mono的话所有的音响会播放同一个音源,而stereo立体声的话不同的音响会播放不同的音源,因此出现了一个channel的概念,通过指定channel可以只取stereo的某个音源的data,设为0的话会按照mono的方式取整个音源。
window:
辅助快速傅里叶变换的窗函数,算法越复杂,声音越柔和,但速度更慢。
2、然后根据这些频谱数据的值来生成cube,根据cube的位置参数生成点,再利用Vecttosity插件画线,就可以实现一个简单音频可视化效果了。
3、关于Mathf.Clamp:
语法:public static float Clamp(float value,float min,float max);
在这里插入图片描述
这个函数可以返回一个最小值到最大值之间的浮点值结果。

实现的代码***

    public AudioSource mAudio;
    /// <summary>
    /// 存放频谱数据的数组长度,长度必须为2的n次方,最小64,最大8192
    /// </summary>
    [Range(64, 128 * 2)]
    public int _sampleLength = 128 * 2;
    [Range(10, 50)]
    public float Frequency = 20;
    /// <summary>
    /// 音频频率数组
    /// </summary>
    public float[] samples;
    public Color lineColor = Color.green;
    //private VectorLine audioLine;
    private List<Vector3> linepoints;
    private VectorLine audioLine;
    public int pointCount;
    public GameObject cubePrefab;
    private Transform[] cubeTransform;//用来生成于频谱同等数量的预制体组
    Vector3 cubePos;//中间位置,用来对比cube位置于此帧的频谱数据
    private void Start()
	{
    
    
        Init();
    }
    private void Init()
    {
    
    
        GameObject tempCube;
        mAudio = GetComponent<AudioSource>();
        samples = new float[_sampleLength];
        pointCount = _sampleLength;
        linepoints = new List<Vector3>(pointCount);
        cubeTransform = new Transform[samples.Length];
        transform.position = new Vector3(-samples.Length * 0.5f, transform.position.y, transform.position.z);
        print("画线初始化开始");
        audioLine = new VectorLine("audioline", linepoints, 5.0f, LineType.Continuous);
        //根据获取的音频长度生成预制体组,并初始化Cube的位置
        for (int i = 0; i < samples.Length; i++)
        {
    
    
            tempCube = Instantiate(cubePrefab, new Vector3(transform.position.x + i, transform.position.y, transform.position.z), Quaternion.identity);
            cubeTransform[i] = tempCube.transform;
            cubeTransform[i].parent = transform;
        }
        audioLine.color = lineColor;
        //audioLine.Draw();
        print("画线结束");
        //audioLine.drawTransform = transform;
    }
    private void Update()
	{
    
    
        //GetAudioData();
    }
    private void LateUpdate()
    {
    
    
        GetAudioData();
    }
    /// <summary>
    /// 根据获取音频频谱更新cube的位置及画线让频谱可视化
    /// </summary>
    private void GetAudioData()
    {
    
    
        //获取频谱
        mAudio.GetSpectrumData(samples, 0, FFTWindow.BlackmanHarris);
        for (int i = 0; i < samples.Length; i++)
        {
    
    
            //linepoints[i]=new Vector3(i, Mathf.Clamp(samples[i] * (50 + i * i * 0.5f), 0, 50), 1);
            //print(linepoints[i]);
            //设置每一个cube的位置
            var Pos = new Vector3(cubeTransform[i].position.x, Mathf.Clamp(samples[i] * (50 + i * i * 0.5f), 0, 100), cubeTransform[i].position.z);
            cubePos = Pos;
            //cubePos.Set(ScreenPos);//频谱的数据主要是用来设置cube的y值,使用Mathf.Clamp将y值限制在一定范围,避免过大
            //频谱值越向后越小,为避免后面的数据变化不明显,所以在扩大sample[i]时,乘以50+i*i*0.5f
            linepoints[i] = cubePos - Vector3.up;//控制线点的位置始终位于预制体下面
            if (cubeTransform[i].position.y < cubePos.y)
            {
    
    
                //当频谱位置大于当前预制体位置,则设为频谱位置
                cubeTransform[i].position = cubePos;
            }
            else if (cubeTransform[i].position.y > cubePos.y)
            {
    
    
                //当频谱位置小于当前预制体位置,则当前位置y值每次减少0.5,形成下落的效果
                cubeTransform[i].position -= new Vector3(0, 0.5f, 0);
            }
        }
        audioLine.Draw();
        if (Event.current.type == EventType.KeyDown || Event.current.type == EventType.KeyUp) return;
    }

实现的效果

在这里插入图片描述

插件和demo下载地址:***

Unity5.4以上的版本都支持的Vectrosity插件
音频可视化源工程

猜你喜欢

转载自blog.csdn.net/qq_42437783/article/details/120128099