直接上效果图(初版):
参考资料:https://blog.csdn.net/liu_if_else/article/details/51233799
https://blog.csdn.net/noEnoughChief/article/details/82984635
另外在B站我也发了自制的可视化音频播放器演示视频,有兴趣的可以看看:
https://www.bilibili.com/video/BV1sC4y1h772
新建个空物体"UI"
按照自己的需求设置UI的中心点(主要是设置中心点的Y值,比如在中间,也就是0.5位置的话,就会上下方向都延伸......)
场景中创建个空物体挂上脚本和音频组件
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
*
* Writer:June
*
* Date: 2019.12.07
*
* Function:音频可视化(2D)
*
* Remarks:
*
*/
public class AudioVisualization2D : MonoBehaviour
{
/// <summary>
/// 声源
/// </summary>
AudioSource _audio;
/// <summary>
/// 音频频率数组 tips:长度必须为2的n次方,最小64,最大8192
/// </summary>
float[] _samples = new float[128];
/// <summary>
/// UIList
/// </summary>
List<GameObject> _uiList = new List<GameObject>();
/// <summary>
/// UI所在的父物体
/// </summary>
public RectTransform _uiParentRect;
void Start()
{
_audio = GetComponent<AudioSource>();//获取声源组件
//获取全部UI
for (int i = 0; i < _uiParentRect.childCount; i++)
_uiList.Add(_uiParentRect.GetChild(i).gameObject);
}
void Update()
{
//获取频谱
_audio.GetSpectrumData(_samples, 0, FFTWindow.BlackmanHarris);
//循环
for (int i = 0; i < _uiList.Count; i++)
{
使用Mathf.Clamp将中间位置的的y限制在一定范围,避免过大
频谱时越向后越小的,为避免后面的数据变化不明显,故在扩大samples[i]时,乘以50+i * i*0.5f
_uiList[i].transform.localScale = new Vector3(1, Mathf.Clamp(_samples[i] * (50 + i * i * 0.5f), 0, 100), 1);
}
}
}
看效果感觉有点奇怪。我觉得不应该直接赋值过去,用个差值可能效果还更好。等待更新,更新完在上传,嘿嘿!
更新:
1.直接把UI做成预设,代码动态生成。
2.一些数据展示在面板上,可进行调节。
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/*
*
* Writer:June
*
* Date: 2019.11.26
*
* Function:音频可视化(2D)
*
* Remarks:
*
*/
public class AudioVisualization2D : MonoBehaviour
{
/// <summary>
/// 声源
/// </summary>
public AudioSource _audio;
/// <summary>
/// 存放频谱数据的数组长度 tips:长度必须为2的n次方,最小64,最大8192(如果你的电脑能承受住的话)
/// </summary>
[Range(64, 128*2)]
public int _sampleLenght = 128 * 2;
/// <summary>
/// 音频频率数组
/// </summary>
private float[] _samples;
/// <summary>
/// UIList
/// </summary>
private List<Image> _uiList = new List<Image>();
/// <summary>
/// UI所在的父物体
/// </summary>
public RectTransform _uiParentRect;
/// <summary>
/// 音频波动条预设
/// </summary>
public GameObject _prefab;
/// <summary>
/// 设置每隔多大距离生成一个UI
/// </summary>
public float _uiDistance;
/// <summary>
/// 下降的幅度比值
/// </summary>
[Range(1, 30)]
public float UpLerp = 12;
void Start()
{
//生成并获取全部UI
CreatUI();
_samples = new float[_sampleLenght];
}
/// <summary>
/// 动态生成UI
/// </summary>
private void CreatUI()
{
for (int i = 0; i < _sampleLenght; i++)
{
GameObject _prefab_GO = Instantiate(_prefab, _uiParentRect.transform);
//为生成的ui命名
_prefab_GO.name = string.Format("Sample[{0}]", i + 1);
_uiList.Add(_prefab_GO.GetComponent<Image>());
RectTransform _rectTransform = _prefab_GO.GetComponent<RectTransform>();
//设置位置
_rectTransform.localPosition = new Vector3(_rectTransform.sizeDelta.x + _uiDistance * i, 0, 0);
}
}
void Update()
{
//获取频谱
_audio.GetSpectrumData(_samples, 0, FFTWindow.BlackmanHarris);
//循环
for (int i = 0; i < _uiList.Count; i++)
{
//使用Mathf.Clamp将中间位置的的y限制在一定范围,避免过大
//频谱时越向后越小的,为避免后面的数据变化不明显,故在扩大samples[i]时,乘以50+i * i*0.5f
Vector3 _v3 = _uiList[i].transform.localScale;
_v3 = new Vector3(1, Mathf.Clamp(_samples[i] * (50 + i * i * 0.5f), 0, 50), 1);
_uiList[i].transform.localScale = Vector3.Lerp(_uiList[i].transform.localScale, _v3, Time.deltaTime * UpLerp);
}
}
}
效果如下,看起来圆滑很多,不够的话,还可以自己调节:
再稍微加工一下,加上后处理、粒子等等...