Anouk added a script that could recognize different pitches in the audio input. I was able to determine the volume of the audio using that script and implemented several interactions that depended on the volume.
private float GetVolume() // finds the loudest pitch to determine the volume of the sound
{
float loudestPitch = 0f;
for (int i = 0; i < AudioPeer._bandBuffer.Length; i++)
{
if (AudioPeer._bandBuffer[i] > loudestPitch)
{
loudestPitch = AudioPeer._bandBuffer[i];
}
}
return loudestPitch;
}
Changing object colors
I thought it could be interesting to change a material color between two colors depending on the amount of audio volume. So I made a script that could change a specific material color. After getting it to work I noticed that it would flicker pretty quickly, because the audio volume could change rather quickly depending on the audio input. To fix this issue I made a tiny delay in getting the volume from the GetVolume() function and interpolated between the previous and current volume colors to get a smooth transition. After I implemented that I showed it to my team.
I got the feedback that I didn't have to change the actual material color, but could just change the color of the specific instance of the material on a mesh. My code didn't work with that in mind, however I agreed that that would be more useful so I decided to refactor my code.
After refactoring the code worked perfectly.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ColorManager : MonoBehaviour
{
public int amountOfColorPairs;
[SerializeField]
private List<GameObject> objectsToColor;
[SerializeField]
private List<GameObject> objectsToColorContainers;
[SerializeField]
private List<Color> minColor;
[SerializeField]
private List<Color> maxColor;
[SerializeField]
private List<Color> currentColor;
[SerializeField]
private VolumeManager volumeManager;
[SerializeField]
private float delayTime = .25f;
private bool delayActive;
private float colorAudioVolume;
private float lerpSpeed = 0.1f;
// Start is called before the first frame update
void Awake()
{
GetAllChildren();
for (int i = 0; i < minColor.Count; i++) // fill the currentColor list so we can change the items later
{
currentColor.Add(minColor[i]);
}
amountOfColorPairs = currentColor.Count;
}
void Update()
{
if (!delayActive)
{
StartCoroutine(Delay());
}
ChangeMaterialColor();
}
IEnumerator Delay() // adds a delay on getting the volume so we get time to lerp between colors so it doesn't flicker
{
delayActive = true;
yield return new WaitForSeconds(delayTime);
colorAudioVolume = volumeManager.volume;
DetermineMaterialColor();
delayActive = false;
}
private void GetAllChildren()
{
for (int i = 0; i < transform.childCount; i++)
{
if (transform.GetChild(i).GetComponent<ColorIndex>())
{
objectsToColor.Add(transform.GetChild(i).gameObject);
}
}
if (objectsToColorContainers.Count > 0)
{
for (int i = 0; i < objectsToColorContainers.Count; i++) // makes it possible to add containers to the list for ease of use.
{
for (int j = 0; j < objectsToColorContainers[i].transform.childCount; j++)
{
if (objectsToColorContainers[i].transform.GetChild(j).GetComponent<ColorIndex>())
{
objectsToColor.Add(objectsToColorContainers[i].transform.GetChild(j).gameObject);
}
}
}
}
}
private void ChangeMaterialColor()
{
for (int i = 0; i < objectsToColor.Count; i++)
{
Color color = objectsToColor[i].GetComponent<MeshRenderer>().material.color;
Color newColor = currentColor[objectsToColor[i].GetComponent<ColorIndex>().colorIndex];
objectsToColor[i].GetComponent<MeshRenderer>().material.color = Color.Lerp(color, newColor, lerpSpeed);
}
}
private void DetermineMaterialColor()
{
for (int i = 0; i < currentColor.Count; i++)
{
float red = CalculateSingleColor(minColor[i].r, maxColor[i].r);
float green = CalculateSingleColor(minColor[i].g, maxColor[i].g);
float blue = CalculateSingleColor(minColor[i].b, maxColor[i].b);
currentColor[i] = new Color(red, green, blue); // the new current color, the object will use this color in ChangeMaterialColor()
}
}
private float CalculateSingleColor(float minColor, float maxColor)
{
float colorScale = colorAudioVolume / 3f; // volume is a value between [0-10], RGB colors in unity are between [0-1]
float inBetweenColor = maxColor - minColor;
float newColor = inBetweenColor = minColor + (inBetweenColor * colorScale);
return newColor;
}
}
The environment reacts based on the audio volume and pitch.