WaitForSeconds 逐渐变得不同步...统一

WaitForSeconds Gradually become out of Sync... Unity

我正在为 google cardboard 创建节奏 VR 游戏,灵感来自 Beat Saber on PS VR 和 Oculus Rift。


概念是随着音乐的节奏,不同方向的方块向你袭来,就像 Beat Saber 中一样。 对于每首音乐,我都创建了一个名为 music 的 ScriptableObject,每个参数都应包含歌曲的难度、名称等,还有一个名为 notes 的 Vector3 数组:第一个Vector 的浮点数对应于从 0 开始的音乐节奏中音符应该被敲打的时间:ScriptableObject

然后在名为 SlashSpawnManagement 的脚本中,其中所有内容都基于 WaitForSeconds(),我生成要粉碎的方块。我真的很难用文字来解释我做的顺序,所以这是一张图片:Explanation

理论上,这个脚本做了什么,它等待一段时间,生成一个块,等待一段时间,生成一个块,等等。逻辑似乎没问题,但这是奇怪的部分。当您播放歌曲时,每个块之间的距离逐渐变得越来越大,这意味着块与音乐越来越不同步。开头很好,但是音乐结尾至少有5秒的间隔


我认为这与帧速率下降有关,所以我尝试将帧速率设置为较低的值:

QualitySettings.vSyncCount = 0;  // VSync must be disabled
Application.targetFrameRate = 30;

但是并没有解决问题。我尝试使用 WaitForSecondsRealtime 而不是 WaitForSeconds,但没有任何变化。我在某处读到 WaitForSeconds 取决于帧速率......在我计算时间的地方,我尝试用 sustractng h 除以一个数字来平衡逐渐的差距。这适用于某些块,但不适用于每个块: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;
    }
}

这将确保您的活动定期举行。

注意:尽管这将是常规的,但不能保证它会与音频等其他系统保持同步。这只能通过在系统之间共享时间来实现,就像 spender 在他对你的问题的评论中提到的那样。

尝试使用 WaitForSeconds 音频计时并希望最好是希望很大。

提前准备好Vector3的列表。如果您想使用节奏准备列表 - 它会起作用。使用AudioSource的time检查每个Update的时机是否正确,并在那个时刻产生一个块。

void Update () {
    SpawnIfTimingIsRight();
}

void SpawnIfTimingIsRight() {
    float nextTiming = timingsArray[nextIndex].x;
    // Time For Block To Get To Position
    float blockTime = this.blockDistanceToTravel / this.blockSpeed;
    float timeToSpawnBlock = nextTiming - blockTime;
    if (this.audioSource.time >= nextTiming && (this.audioSource.time - Time.deltaTime) < nextTiming) {
        // Spawn block
    }
}