WaitForSeconds逐渐变得不同步... Unity

时间:2018-10-31 12:43:55

标签: c# android unity3d wait frame-rate

我正在为Google硬纸板创建一个节奏VR游戏,灵感来自PSVR和Oculus Rift上的 Beat Saber


概念是,按照音乐的节奏,具有不同方向的块会出现在您的身旁,就像 Beat (剑) Sabre 中一样。 对于每一种音乐,我都创建了一个名为 ScriptableObject 的音乐,每个参数都应包含歌曲的难度,名称等,但还应包含一个称为notes的Vector3数组:向量对应于从0:ScriptableObject

开始在音乐节奏中敲打音符的时间

然后在名为 SlashSpawnManagement 的脚本中,其中所有内容均基于WaitForSeconds(),我生成了要粉碎的块。我很难按顺序解释这些单词,所以这是一张图片:Explanation

从理论上讲,此脚本的作用是等待一段时间,生成一个块,等待一段时间,生成一个块,等等。逻辑似乎还可以,但这是奇怪的部分。当您播放歌曲时,每个块之间的距离逐渐变大,这意味着这些块与音乐越来越不同步。它的开始非常好,但是在音乐结束时,至少有5s的间隔。


我认为这与帧速率下降有关,因此我尝试通过以下方式将frameRate设置为较低的值:

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

但是它不能解决问题。我尝试使用 WaitForSecondsRealtime 而不是 WaitForSeconds ,但没有任何变化。我读过某个地方,WaitForSeconds取决于帧速率...在计算时间的地方,我尝试用h除以一个数字,以消除逐渐的差距。这适用于某些块,但不是每个块:Notes[j][0] - h / 500


所以这是我的问题,如何使WaitForSeconds或与提供的秒数一致的任何其他方法?

先谢谢您

PS:需要更多说明,请提出并原谅我的错别字和我的英语:)

2 个答案:

答案 0 :(得分:3)

如果您希望在固定的时间间隔内发生某些事情,确保错误不会累积很重要。

不要:

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;
    }
}

这将确保您的事件定期发生。

注意:即使这是常规的操作,也不能保证与其他系统(例如音频)保持同步。这只能通过在系统之间共享时间来实现,就像支出者在对您的问题的评论中提到的那样。

答案 1 :(得分:2)

尝试使用WaitForSecond安排音频的时间,并希望获得最好的希望。

具有预先准备的Vector3列表。如果您想使用节奏来准备列表,它将起作用。使用AudioSource的时间检查每个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
    }
}