本文涉及的原始碼包含在安卓Unity渲染互通的 Demo 裡,直接開啟 Unity 工程的 Test 場景就行,不用管安卓工程。
指令碼控制粒子
起初是看到這麼一篇部落格 Shader特效—— 音符跳動,效果如下圖:
具體的shader程式碼就不貼在這裡了,他的部落格裡都有。
處理音訊的關鍵程式碼如下:
private int m_NumSamples = 256;
private float[] m_Samples;
private float sum, rms;
private void Start()
{
audioSource = GetComponent<AudioSource>();
audioSource.clip = Microphone.Start(null, true, 10, 44100);
m_Samples = new float[m_NumSamples];
}
private void Update()
{
audioSource.GetOutputData(m_Samples, 0);
sum = m_Samples[m_NumSamples - 1] * m_Samples[m_NumSamples - 1];
rms = Mathf.Sqrt(sum/* / m_NumSamples*/);
float intensity = rms;
Debug.Log(intensity);
if (intensity > bootIntensity)
{
//change in shader
material.SetFloat("_Intensity", intensity);
}
else
{
material.SetFloat("_Intensity", 0);
}
}
那麼能不能用到粒子效果上呢,查了一下API果然不難做到。
這裡用一個球狀發射的粒子模組來做示例:
我希望粒子隨著音樂發射,音量越大數量越多,於是乎我們需要在指令碼內通過檢測音量來改變 Emission 模組的 Rate over Time 值(只是舉個例子,當然有其他更漂亮的實現)
一開始我盲寫,果然有 rateOverTime 這個值,但是不允許我直接更改。
查了下 API-ParticleSystem.EmissionModule 後發現不能直接用指令碼賦值,而是需要例項化之後賦值:
var emission = m_ParticleSystem.emission;
emission.rateOverTime = 100f;
那麼事情就好辦了,複用上面的指令碼程式碼就可以控制粒子了:
private void Update()
{
var emission = m_ParticleSystem.emission;
audioSource.GetOutputData(m_Samples, 0);
sum = m_Samples[m_NumSamples - 1] * m_Samples[m_NumSamples - 1];
rms = Mathf.Sqrt(sum/* / m_NumSamples*/);
float intensity = rms;
Debug.Log(intensity);
if (intensity > bootIntensity)
{
emission.rateOverTime = 10f * (1 + intensity * 1000);
}
else
{
emission.rateOverTime = 10f;
}
}
接入Mic
Unity給的介面很方便,在指令碼中開啟Mic即可,具體程式碼如下:
private void Start()
{
audioSource = GetComponent<AudioSource>();
BeginListener(0);
//audioSource.clip = Microphone.Start(null, true, 10, 44100);
m_Samples = new float[m_NumSamples];
}
......
public void BeginListener(int index)
{
int min = 0;
int max = 0;
Microphone.GetDeviceCaps(Microphone.devices[index], out min, out max);
audioSource.clip = Microphone.Start(Microphone.devices[index], true, 2, max);
while (!(Microphone.GetPosition(Microphone.devices[index]) > 1))
{
// Wait until the recording has started
}
audioSource.loop = true;
audioSource.Play();
}
對著Mic吼的效果如下:
不建議在辦公室吼,吹氣也可以達到這樣的效果。
本人不太熟悉粒子系統,有興趣的朋友可以自己實現更多更酷的特效。