【发布时间】:2018-12-03 20:46:19
【问题描述】:
我的问题很简单,但我很难找到答案。简短的上下文,我有一个根据麦克风输入在 Y 轴上移动的精灵。之前,我提示用户记录他们的最低和最高音符,计算这两个音符的频率,并将其用作在 Y 轴上定位精灵的参考。
假设最低音符为 100 Hz,最高音符为 400 Hz。因此,如果玩家发出 100 Hz 的音调,精灵应该向下移动到 Y 轴的底部。要回到中心(Y 位置 0),演奏者必须发出 250 Hz 的音调(100 到 400 之间的中点)。
所以我们知道对于那个播放器,250 Hz 等于 Y 位置 0。但我需要知道最低音符(底部边缘)和最高音符(顶部边缘)的 Y 位置等效值。当我手动将精灵移动到顶部边缘并查看检查器中的 Y 值时,它显然是 4.58。但我不确定硬编码 4.58 是否可以在不同屏幕尺寸的设备上很好地扩展。
截图在这里:https://i.ibb.co/pjrkSNV/Capture.png
理想情况下,我希望有一个名为 FrequencyToY(float frequency) 的方法,它将频率值转换为轴上相应的 Y 值。我在 PlayerPrefs 中保存了最低和最高频率值。关于精灵运动的重要说明,我不想要重力。每次播放器发出声音时,小鸟都应该平稳地移动到相应的 Y 位置,否则保持在原地。
这是我当前附加到我的精灵的脚本:
public class Player : MonoBehaviour
{
public AudioSource audioPlayer;
public AudioMixer masterMixer;
private float[] _spectrum;
private float _fSample;
private Transform playerTransform;
void Start()
{
playerTransform = transform;
//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");
//This is how I'd like to call the function
//But if someone could change this and make the sprite actually
//"move" to that point instead of just popping there it would be awesome!
transform.position = new Vector2(0, FrequencyToY(pitchVal));
}
}
//Converts frequency to position on Y-axis
public float FrequencyToY(float frequency)
{
float x = 0;
return x;
}
}
【问题讨论】: