【问题标题】:WaitForSeconds Gradually become out of Sync... UnityWaitForSeconds 逐渐变得不同步... Unity
【发布时间】:2018-10-31 12:43:54
【问题描述】:

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


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

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

理论上,这个脚本的作用是等待一段时间,生成一个块,等待一段时间,生成一个块,等等。逻辑看起来不错,但这是奇怪的部分。随着您播放歌曲,每个块之间的距离逐渐变得越来越大,这意味着块与音乐越来越不同步。开头很好,但在音乐结束时至少有 5s 的间隙。


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

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

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


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

提前谢谢你,

PS : 如需更多说明,请询问并原谅我的拼写错误和我的英语:)

【问题讨论】:

  • 如果您正在用有节奏的声音做任何事情,那么使用音频来驱动一切的时间是必不可少的。我不确定如何统一实现这一点,但使用音频以外的任何计时机制都会导致同步丢失。你的声音输出的时间应该运行节目。音频时钟不与任何线程计时器/屏幕计时器保持同步。
  • docs.unity3d.com/ScriptReference/AudioSettings-dspTime.html 是音频方面唯一真正的时间来源。
  • @spender 非常感谢。

标签: c# android unity3d wait frame-rate


【解决方案1】:

如果您希望某事以固定的时间间隔发生,请务必确保错误不会累积。

不要:

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

这将确保您的活动定期发生。

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

【讨论】:

  • 这非常符合我的想法。虽然 dsp 时钟可能会稍微偏离 Time.time,但几分钟后应该很难测量
【解决方案2】:

尝试使用 WaitForSeconds 音频的时机,并希望最好的希望是一个很大的希望。

提前准备好 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
    }
}

【讨论】:

  • 没问题,朋友。
猜你喜欢
  • 2015-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-05
  • 2014-06-21
  • 1970-01-01
  • 2020-01-21
  • 2010-12-17
相关资源
最近更新 更多