我正在为 Google Cardboard 创建一款节奏 VR 游戏,灵感来自于 PSVR 和 Oculus Rift 上的 Beat Saber。
这个概念是不同方向的方 block 随着音乐的节奏向你袭来,就像BeatSaber中一样。 对于每首音乐,我都创建了一个名为 music 的 ScriptableObject ,它应该包含每个参数,例如歌曲的难度、名称等,而且还包含一个名为 Notes 的 Vector3 数组:向量对应于从 0 开始的音乐节奏中应敲击音符的时间:ScriptableObject
然后在一个名为 SlashSpawnManagement 的脚本中,其中所有内容都基于 WaitForSeconds(),我生成要粉碎的 block 。我真的很难用文字解释我这样做的顺序,所以这里有一张图片:Explanation
理论上,这个脚本的作用是,等待一段时间,生成一个 block ,等待一段时间,生成一个 block ,等等。逻辑看起来不错,但这是奇怪的部分。当您播放歌曲时,每个 block 之间的距离逐渐变得越来越大,这意味着 block 与音乐越来越不同步。开头很好,但音乐结束时至少有5秒的间隙。
我认为这与帧速率下降有关,因此我尝试将帧速率设置为较低的值:
QualitySettings.vSyncCount = 0; // VSync must be disabled
Application.targetFrameRate = 30;
但这并不能解决问题。我尝试使用 WaitForSecondsRealtime 而不是 WaitForSeconds,但没有任何变化。我在某处读到 WaitForSeconds 取决于帧速率...在我计算时间的地方,我尝试将 h 除以一个数字来平衡逐渐的间隙。这适用于某些 block ,但不适用于每个 block :Notes[j][0] - h/500
所以这是我的问题,如何使 WaitForSeconds 或任何其他方法与提供的秒数一致?
提前谢谢您,
PS:如需更多说明,请询问并请原谅我的打字错误和我的英语:)
最佳答案
如果您希望定期发生某些事情,请务必确保错误不会累积。
不要:
private IEnumerable DoInIntervals()
{
while (this)
{
yield return new WaitForSeconds(1f); // this will NOT wait exactly 1 second but a few ms more. This error accumulates over time
DoSomething();
}
}
做:
private IEnumerable DoInIntervals()
{
const float interval = 1f;
float nextEventTime = Time.time + interval;
while (this)
{
if (Time.time >= nextEventTime)
{
nextEventTime += interval; // this ensures that nextEventTime is exactly (interval) seconds after the previous nextEventTime. Errors are not accumulated.
DoSomething();
}
yield return null;
}
}
这将确保您的事件定期发生。
注意:尽管这是常规的,但并不能保证它会与音频等其他系统保持同步。这只能通过在系统之间共享时间来实现,就像花费者在对您的问题的评论中提到的那样。
关于c# - WaitForSeconds 逐渐变得不同步... Unity,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53083635/