- Home /
Getting the “edge Y-values”
My problem is pretty simple, but yet I struggle to find an answer. Brief context, I have a sprite that moves accross the Y-axis according to microphone input. Beforehand, I prompted the user to record their lowest and highest note, calculated the frequency of these two notes and am using it as a reference for positioning the sprite on the Y-axis.
Let's say the lowest note is 100 Hz and the highest one 400 Hz. So if the player makes a tone of 100 Hz, the sprite should move down to the bottom of the Y-axis. To move back to the center (Y-position 0), the player would have to make a tone of 250 Hz (midpoint between 100 and 400).
So we know that for that player, 250 Hz equals to Y-position 0. But I need to know the Y-position equivalents of the lowest note (bottom edge) and highest note (top edge). When I move the sprite manually to the top edge and look at the Y-value in the inspector, it's apparently 4.58. But I'm not sure if hard-coding 4.58 would scale well across different screen-sized devices.
Screenshot here: https://i.ibb.co/pjrkSNV/Capture.png
I ideally want to have a method called FrequencyToY(float frequency) that converts a frequency value to the corresponding Y-value on the axis. I saved the lowest and highest frequency values in PlayerPrefs. Important note about the sprite movement, I don't want gravity. The bird should just smoothly move to the corresponding Y-position every time the player produces a tone, and stay in place otherwise.
This is my current script attached to the sprite:
public class Player : MonoBehaviour
{
public AudioSource audioPlayer;
public AudioMixer masterMixer;
private float[] _spectrum;
private float _fSample;
//New code
private float lerp_speed;
private float lowest_y;
private float highest_y;
void Start()
{
//New code
lerp_speed = 3;
lowest_y = -4.58f;
highest_y = 4.58f;
//Code for microphone loop
masterMixer.SetFloat("masterVolume", -80f);
_spectrum = new float[AudioAnalyzer.QSamples];
_fSample = AudioSettings.outputSampleRate;
audioPlayer.clip = Microphone.Start("", true, 10, 44100);
audioPlayer.loop = true;
while(!(Microphone.GetPosition("") > 0)) { }
audioPlayer.Play();
}
void Update()
{
//Calculate frequency of currently detected tones
audioPlayer.GetSpectrumData(_spectrum, 0, FFTWindow.BlackmanHarris);
float pitchVal = AudioAnalyzer.calculateFrequency(ref _spectrum, _fSample);
if(pitchVal != 0)
{
if (pitchVal < PlayerPrefs.GetFloat("lowestFrequency"))
pitchVal = PlayerPrefs.GetFloat("lowestFrequency");
else if (pitchVal > PlayerPrefs.GetFloat("highestFrequency"))
pitchVal = PlayerPrefs.GetFloat("highestFrequency");
//New code
Vector2 goal_position = new Vector2(0, FrequencyToY(pitchVal));
transform.position = Vector2.Lerp(transform.position, goal_position, Time.deltaTime * lerp_speed);
}
}
//New code
public float FrequencyToY(float frequency)
{
float relative_frequency = Mathf.InverseLerp(PlayerPrefs.GetFloat("lowestFrequency"), PlayerPrefs.GetFloat("lowestFrequency"), frequency);
return Mathf.Lerp(lowest_y, highest_y, relative_frequency);
}
}
Answer by sSuite · Dec 04, 2018 at 06:17 AM
This should be pretty simple! You'll just need to do something like this:
float relative_frequency = Mathf.InverseLerp(lowest_frequency, highest_frequency, frequency);
return Mathf.Lerp(lowest_y, highest_y, relative_frequency);
As for your worry that the Y positions might not scale with screen sizes, that's a reasonable concern. You might want to do this on a UI canvas instead, which will be able to automatically move things around to fit on any screen dimensions.
Oh, also! This is a little hacky, but you could lerp to the goal position rather than teleporting to it:
Vector2 goal_position = new Vector2(0, FrequencyToY(pitchVal));
transform.position = Vector2.Lerp(transform.position, goal_position, Time.deltaTime * lerp_speed);
Hope this helps!
First of all thank you so much for helping me! It's my first time making an actual game, I have been only making console apps for 2 years at school, so this new world is a bit overwhel$$anonymous$$g. Could you please explain how I could get the values for lowest_y
, highest_y
, and lerp_speed
?
lowest_y and highest_y you can get by doing exactly what you were doing before. Generally speaking, I think Unity's cameras will maintain the vertical field of view at the expense of the horizontal one if you change the aspect ratio of the screen -- so you're probably fine just measuring the positions you want in the level.
As for lerp_speed, that can be any float! I'd try maybe 5 or 10, but you can play around with it and see what you like.
I added your code but I think I did something wrong. The bird keeps moving down, even when I produce a high tone. I uploaded a video to illustrate the problem: https://youtu.be/8yopaG1tD1c. Sorry for the crappy audio, I recorded it with Windows' Game Bar... I also updated the code in my original post (new code is preceded by //New code
), could you please help me out?
Your answer

Follow this Question
Related Questions
player is shake up-down? 0 Answers
making models move correctly 1 Answer
Can't teleport on the X axis 2 Answers
How enemy AI follows player without diagonal movement? (2D) 0 Answers
How to move an object in y-axis? 0 Answers