【问题标题】:android gdx sound performance issueandroid gdx 声音性能问题
【发布时间】:2017-10-17 20:40:43
【问题描述】:

我正在使用 libgdx 构建一个滚动射击游戏。在 Windows 中,一切运行良好,但在 android 上我得到明显的抖动,帧速率从 61 fps avg 没有声音下降到 48-56 fps avg 有声音。它同时播放许多小音效,因为有很多子弹要发射,敌人要同时击中。我的声音例程:

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Sound;

public class SoundFX {

    static final int BGDIE = 1, BGHIT = 2, BGLASER = 3, BGSPAWN = 4, PDIE = 5, PHIT = 6, PLASER = 7, PSPAWN = 8, PAUSE = 9;
    Sound S_BGDIE, S_BGHIT, S_BGLASER, S_BGSPAWN, S_PDIE, S_PHIT, S_PLASER, S_PSPAWN, S_PAUSE;

    public void load()
    {
        S_BGDIE = Gdx.audio.newSound(Gdx.files.internal("data/sfx/badguydie.mp3"));
        S_BGHIT = Gdx.audio.newSound(Gdx.files.internal("data/sfx/badguygothit.mp3"));
        S_BGLASER = Gdx.audio.newSound(Gdx.files.internal("data/sfx/badguylaser.mp3"));
        S_BGSPAWN = Gdx.audio.newSound(Gdx.files.internal("data/sfx/badguyspawn.mp3"));
        S_PDIE = Gdx.audio.newSound(Gdx.files.internal("data/sfx/playerdie.mp3"));
        S_PHIT = Gdx.audio.newSound(Gdx.files.internal("data/sfx/playergothit.mp3"));
        S_PLASER = Gdx.audio.newSound(Gdx.files.internal("data/sfx/playerlaser.mp3"));
        S_PSPAWN = Gdx.audio.newSound(Gdx.files.internal("data/sfx/playerspawn.mp3"));
        S_PAUSE = Gdx.audio.newSound(Gdx.files.internal("data/sfx/pause.mp3"));
    }

    public void unload()
    {
        S_BGDIE.dispose();
        S_BGHIT.dispose();
        S_BGLASER.dispose();
        S_BGSPAWN.dispose();
        S_PDIE.dispose();
        S_PHIT.dispose();
        S_PLASER.dispose();
        S_PSPAWN.dispose();
        S_PAUSE.dispose();
    }

    public void play(int id)
    {
        switch(id)
        {
        case BGDIE:
            S_BGDIE.play();
            break;
        case BGHIT:
            S_BGHIT.play();
            break;
        case BGLASER:
            S_BGLASER.play();
            break;
        case BGSPAWN:
            S_BGSPAWN.play();
            break;
        case PDIE:
            S_PDIE.play();
            break;
        case PHIT:
            S_PHIT.play();
            break;
        case PLASER:
            S_PLASER.play();
            break;
        case PSPAWN:
            S_PSPAWN.play();
            break;
        case PAUSE:
            S_PAUSE.play();
            break;
        default:
            System.out.println("invalid sfx call");
            break;
        }
    }
}

根据游戏中发生的情况,播放大约每秒被调用 4-10 次,声音效果持续时间不到一秒,平均每个 8kb。

这里发生了什么,我该如何解决这个问题?它使游戏看起来非常不专业,并且在困难的关卡中几乎无法玩。

【问题讨论】:

    标签: android performance audio libgdx


    【解决方案1】:

    关于为什么您在播放多个声音时注意到性能下降如此之大的问题的一些背景知识。这是因为在幕后 libgdx 需要在将声音播放回用户之前将它们混合在一起。当您同时运行一定数量的声音时,对系统进行混音的要求会变得非常高。由于您可能会在渲染线程上尝试播放声音,因此需求的增加会导致帧率下降。

    根据我对游戏中任何类型音效的经验,当您遇到同时播放大量小声音的情况时,几乎没有解决方案。我将把这些写成比 libGDX 具体更通用的解决方案:

    1) 在一个线程上播放所有声音

    这就是您目前正在做的事情,虽然它在播放大量声音时效果不佳,但它很容易实现并且在大多数情况下都可以使用。但是,一旦您获得足够多的声音一起播放,您就会注意到延迟和质量差。

    2) 在与渲染线程不同的线程上播放声音

    这是一种可能的方法(取决于框架是否允许),它不是很好,因为它不能很好地扩展。但是,如果您只是遭受轻微的性能损失并且不希望同时播放大量(~20+)声音,这是一个相对较小的更改,通常可以解决问题。

    3) 播放声音上限

    此解决方案需要更多工作,如果您有必须播放的声音,则可能无法接受。您只需跟踪播放的声音数量并允许播放其他声音,直到您达到某个点。任何超过上限的内容都不会播放。这使您可以保证一定的性能水平。这种方法的最大缺点是,如果你在角色受重伤并且没有播放时播放声音,那么这可能会让用户感到不安,因为他们可能正在听声音以知道他们是否会很快死去,却发现自己死了。

    4) 有选择地播放重要的声音

    这有点难以实现,但它的效果非常好,因为您实际上是在设置性能上限。您要做的是确定播放声音的优先级。它离你很近吗?声音大吗?是不是重要?然后,您只播放重要到足以播放到某个上限(可能是 4、6、8 等)的声音。您还需要跟踪当前播放的声音数量,以确定在给定点可以播放多少新声音。

    【讨论】:

    • 谢谢!非常广泛的答案。现在我知道在哪里寻找以及如何解决它。我首先要看看对并发声音设置上限是否可以解决问题。如果是这样,我将添加合理的优先级。如果没有,我将使用优先级较低的单独声音线程。
    【解决方案2】:

    一种解决方法:播放对玩家来说不太重要的声音,只有当当前 FPS 高于某个值时才能播放它们。例如:

    if (Gdx.graphics.getFramesPerSecond() > 56) playSound();
    

    无论 FPS 值如何,都应始终播放重要的声音。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多