getPosition函数多次调用会返回同样的结果

我在制作一款节奏游戏,想要获得正在播放音乐的准确时间,翻阅大量论坛资料后,发现使用myChannel.getPosition(out uint position, FMOD.TIMEUNIT.MS);能比较精确的获得准确的时间位置,并且我尝试用代码将音乐时间和节奏同步也有不错的表现,但我将结果打印到控制台后发现,多次调用(如:在Update这种每帧更新的函数中调用)可能会返回同样的结果,暂时没有发现多次同样的结果给游戏功能带来什么影响,因为更新速度其实比较快。但我比较好奇的是:
1、是怎样的原因造成这样的问题,是因为FMOD的每次混音的更新周期慢于引擎的更新周期吗?
2、如果我想让每次结果不一样,保持线性增长,我该做什么处理?

你好,

我在用Unity复现的时候观察到,FMOD的混音器更新的频率应该是低于Unity引擎的Update方法的调用频率的。我发现如果将DSP缓冲区设置的更大的话会影响myChannel.getPosition 更新的频率。正如你所提到的,通常来说这并不会在你的游戏中造成明显的问题,但如果你想提高时间的精确度,一个可选的方案是可以尝试减小DSP缓冲区。不过请注意这种方式有可能对CPU不太友好,因为减小DSP缓冲区有可能会导致CPU在处理FMOD的音频的缓冲区时变得更加卡顿。

目前我没有找到一个足够好的解决方案。如果你希望每次调用 getPosition 都返回线性增长的时间位置,你可以考虑使用 getPosition 返回的值作为参照,如果当前位置与上一次的位置相同,则手动累计 Time.deltaTime。最后再将累计的时间加到上一次的时间位置上,以确保每次都得到不同的结果。例如:

private uint lastKnownPosition; //上一次的时间位置
private float accumulatedTime; //累计的时间

void Start()
{
    myChannel.getPosition(out lastKnownPosition, FMOD.TIMEUNIT.MS);
    accumulatedTime = 0;
}

void Update()
{
    uint currentPosition;
    myChannel.getPosition(out currentPosition, FMOD.TIMEUNIT.MS);
    
    if (currentPosition != lastKnownPosition)
    {
        // FMOD的时间位置有更新, 累计时间不做变动
        accumulatedTime = 0;
        lastKnownPosition = currentPosition;
    }
    else
    {
        // FMOD的时间位置没有更新,手动推进时间
        accumulatedTime += Time.deltaTime * 1000.0f; // 转换为毫秒
    }

    // 最后叠加手动推进的累计时间,确保返回一个不同的结果
    uint finalPosition = lastKnownPosition + (uint)accumulatedTime;
    Debug.Log($"Final Position: {finalPosition} ms");
}

希望这些对你有帮助,有任何问题的话,请不要犹豫尽管提问。

1 Like

非常感谢解答我的疑惑!感觉思路清晰了,我会参考尝试一下给出的解决方案,虽然等了好多天,但这些回答对我项目推进有很大帮助!

1 Like